From patchwork Wed Aug 31 12:58:25 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Graeme Russ X-Patchwork-Id: 112551 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id A3EDBB6F72 for ; Wed, 31 Aug 2011 22:59:08 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 502E528096; Wed, 31 Aug 2011 14:59:07 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hq3pRCJjyJba; Wed, 31 Aug 2011 14:59:07 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 639C62807F; Wed, 31 Aug 2011 14:59:04 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BA0C22807F for ; Wed, 31 Aug 2011 14:59:01 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ouy+-cxAsIxk for ; Wed, 31 Aug 2011 14:58:59 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-gw0-f44.google.com (mail-gw0-f44.google.com [74.125.83.44]) by theia.denx.de (Postfix) with ESMTPS id 3063A28078 for ; Wed, 31 Aug 2011 14:58:57 +0200 (CEST) Received: by gwb20 with SMTP id 20so29902gwb.3 for ; Wed, 31 Aug 2011 05:58:56 -0700 (PDT) Received: by 10.236.145.200 with SMTP id p48mr1907359yhj.33.1314795536201; Wed, 31 Aug 2011 05:58:56 -0700 (PDT) Received: from localhost.localdomain (d122-104-32-184.sbr6.nsw.optusnet.com.au [122.104.32.184]) by mx.google.com with ESMTPS id x42sm1093468yhm.79.2011.08.31.05.58.41 (version=SSLv3 cipher=OTHER); Wed, 31 Aug 2011 05:58:55 -0700 (PDT) From: Graeme Russ To: u-boot@lists.denx.de Date: Wed, 31 Aug 2011 22:58:25 +1000 Message-Id: <1314795505-14321-1-git-send-email-graeme.russ@gmail.com> X-Mailer: git-send-email 1.7.5.2.317.g391b14 In-Reply-To: <1314794155-14186-1-git-send-email-graeme.russ@gmail.com> References: <1314794155-14186-1-git-send-email-graeme.russ@gmail.com> Subject: [U-Boot] [PATCH V4] console: Implement pre-console buffer X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 Acked-by: Mike Frysinger Acked-by: Simon Glass --- 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(-) -- 1.7.5.2.317.g391b14 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; }