Commit 9558b48a authored by Graeme Russ's avatar Graeme Russ Committed by Wolfgang Denk

console: Implement pre-console buffer

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

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

The pre-console buffer will buffer the last CONFIG_PRE_CON_BUF_SZ bytes
Any earlier characters are silently dropped.
parent cc9abfe4
...@@ -619,6 +619,20 @@ The following options need to be configured: ...@@ -619,6 +619,20 @@ The following options need to be configured:
must be defined, to setup the maximum idle timeout for must be defined, to setup the maximum idle timeout for
the SMC. 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 - Boot Delay: CONFIG_BOOTDELAY - in seconds
Delay before automatically booting the default image; Delay before automatically booting the default image;
set to -1 to disable autoboot. set to -1 to disable autoboot.
......
...@@ -38,6 +38,9 @@ typedef struct global_data { ...@@ -38,6 +38,9 @@ typedef struct global_data {
unsigned long flags; unsigned long flags;
unsigned long baudrate; unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */ 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_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */ unsigned long fb_base; /* base address of frame buffer */
......
...@@ -38,6 +38,9 @@ typedef struct global_data { ...@@ -38,6 +38,9 @@ typedef struct global_data {
unsigned long baudrate; unsigned long baudrate;
unsigned long stack_end; /* highest stack address */ unsigned long stack_end; /* highest stack address */
unsigned long have_console; /* serial_init() was called */ 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 reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of env struct */ unsigned long env_addr; /* Address of env struct */
unsigned long env_valid; /* Checksum of env valid? */ unsigned long env_valid; /* Checksum of env valid? */
......
...@@ -45,6 +45,9 @@ typedef struct global_data { ...@@ -45,6 +45,9 @@ typedef struct global_data {
unsigned long board_type; unsigned long board_type;
unsigned long baudrate; unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */ 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 */ phys_size_t ram_size; /* RAM size */
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long env_valid; /* Checksum of Environment valid? */
......
...@@ -57,6 +57,9 @@ typedef struct global_data { ...@@ -57,6 +57,9 @@ typedef struct global_data {
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long have_console; /* serial_init() was called */ 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) #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
unsigned long fb_base; /* Base addr of framebuffer memory */ unsigned long fb_base; /* Base addr of framebuffer memory */
#endif #endif
......
...@@ -39,6 +39,9 @@ typedef struct global_data { ...@@ -39,6 +39,9 @@ typedef struct global_data {
unsigned long flags; unsigned long flags;
unsigned long baudrate; unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */ 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_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */ unsigned long fb_base; /* base address of frame buffer */
......
...@@ -41,6 +41,9 @@ typedef struct global_data { ...@@ -41,6 +41,9 @@ typedef struct global_data {
unsigned long flags; unsigned long flags;
unsigned long baudrate; unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */ 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 */ phys_size_t ram_size; /* RAM size */
unsigned long reloc_off; /* Relocation Offset */ unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
......
...@@ -29,6 +29,9 @@ typedef struct global_data { ...@@ -29,6 +29,9 @@ typedef struct global_data {
unsigned long baudrate; unsigned long baudrate;
unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long have_console; /* serial_init() was called */ 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 */ phys_size_t ram_size; /* RAM size */
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid */ unsigned long env_valid; /* Checksum of Environment valid */
......
...@@ -138,6 +138,9 @@ typedef struct global_data { ...@@ -138,6 +138,9 @@ typedef struct global_data {
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long have_console; /* serial_init() was called */ 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) #if defined(CONFIG_SYS_ALLOC_DPRAM) || defined(CONFIG_CPM2)
unsigned int dp_alloc_base; unsigned int dp_alloc_base;
unsigned int dp_alloc_top; unsigned int dp_alloc_top;
......
...@@ -34,6 +34,9 @@ typedef struct global_data ...@@ -34,6 +34,9 @@ typedef struct global_data
unsigned long baudrate; unsigned long baudrate;
unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long have_console; /* serial_init() was called */ 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 */ phys_size_t ram_size; /* RAM size */
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid */ unsigned long env_valid; /* Checksum of Environment valid */
......
...@@ -53,6 +53,9 @@ typedef struct global_data { ...@@ -53,6 +53,9 @@ typedef struct global_data {
unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long have_console; /* serial_init() was called */ 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) #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
unsigned long fb_base; /* Base address of framebuffer memory */ unsigned long fb_base; /* Base address of framebuffer memory */
#endif #endif
......
...@@ -40,6 +40,9 @@ typedef struct global_data { ...@@ -40,6 +40,9 @@ typedef struct global_data {
unsigned long flags; unsigned long flags;
unsigned long baudrate; unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */ 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 reloc_off; /* Relocation Offset */
unsigned long load_off; /* Load Offset */ unsigned long load_off; /* Load Offset */
unsigned long env_addr; /* Address of Environment struct */ unsigned long env_addr; /* Address of Environment struct */
......
...@@ -329,6 +329,39 @@ int tstc(void) ...@@ -329,6 +329,39 @@ int tstc(void)
return serial_tstc(); 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) void putc(const char c)
{ {
#ifdef CONFIG_SILENT_CONSOLE #ifdef CONFIG_SILENT_CONSOLE
...@@ -342,7 +375,7 @@ void putc(const char c) ...@@ -342,7 +375,7 @@ void putc(const char c)
#endif #endif
if (!gd->have_console) if (!gd->have_console)
return; return pre_console_putc(c);
if (gd->flags & GD_FLG_DEVINIT) { if (gd->flags & GD_FLG_DEVINIT) {
/* Send to the standard output */ /* Send to the standard output */
...@@ -366,7 +399,7 @@ void puts(const char *s) ...@@ -366,7 +399,7 @@ void puts(const char *s)
#endif #endif
if (!gd->have_console) if (!gd->have_console)
return; return pre_console_puts(s);
if (gd->flags & GD_FLG_DEVINIT) { if (gd->flags & GD_FLG_DEVINIT) {
/* Send to the standard output */ /* Send to the standard output */
...@@ -383,8 +416,10 @@ int printf(const char *fmt, ...) ...@@ -383,8 +416,10 @@ int printf(const char *fmt, ...)
uint i; uint i;
char printbuffer[CONFIG_SYS_PBSIZE]; char printbuffer[CONFIG_SYS_PBSIZE];
#ifndef CONFIG_PRE_CONSOLE_BUFFER
if (!gd->have_console) if (!gd->have_console)
return 0; return 0;
#endif
va_start(args, fmt); va_start(args, fmt);
...@@ -404,8 +439,10 @@ int vprintf(const char *fmt, va_list args) ...@@ -404,8 +439,10 @@ int vprintf(const char *fmt, va_list args)
uint i; uint i;
char printbuffer[CONFIG_SYS_PBSIZE]; char printbuffer[CONFIG_SYS_PBSIZE];
#ifndef CONFIG_PRE_CONSOLE_BUFFER
if (!gd->have_console) if (!gd->have_console)
return 0; return 0;
#endif
/* For this to work, printbuffer must be larger than /* For this to work, printbuffer must be larger than
* anything we ever want to print. * anything we ever want to print.
...@@ -547,6 +584,8 @@ int console_init_f(void) ...@@ -547,6 +584,8 @@ int console_init_f(void)
gd->flags |= GD_FLG_SILENT; gd->flags |= GD_FLG_SILENT;
#endif #endif
print_pre_console_buffer();
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment