console: Add a console buffer
authorSimon Glass <sjg@chromium.org>
Mon, 9 Nov 2015 06:47:48 +0000 (23:47 -0700)
committerSimon Glass <sjg@chromium.org>
Fri, 20 Nov 2015 03:27:50 +0000 (20:27 -0700)
It is useful to be able to record console output and provide console input
via a buffer. This provides sandbox with the ability to run a command and
check its output. If the console is set to silent then no visible output
is generated.

This also provides a means to fix the problem where tests produce unwanted
output, such as errors or warnings. This can be confusing. We can instead
set the console to silent and record this output. It can be checked later
in the test if required.

It is possible that this may prove useful for non-test situations. For
example the console output may be suppressed for normal operations, but
recorded and stored for access by the OS. That feature is not implemented
at present.

Signed-off-by: Simon Glass <sjg@chromium.org>
common/Kconfig
common/board_f.c
common/board_r.c
common/console.c
include/asm-generic/global_data.h
include/console.h

index 620d41f9ea63ba15463e95aedbbb0c5979e6d395..ccf5475bac63ae4b2e2ff54ed1afe4b258f996b3 100644 (file)
@@ -679,3 +679,31 @@ config CMD_TPM_TEST
 endmenu
 
 endmenu
+
+config CONSOLE_RECORD
+       bool "Console recording"
+       help
+         This provides a way to record console output (and provide console
+         input) through cirular buffers. This is mostly useful for testing.
+         Console output is recorded even when the console is silent.
+         To enable console recording, call console_record_reset_enable()
+         from your code.
+
+config CONSOLE_RECORD_OUT_SIZE
+       hex "Output buffer size"
+       depends on CONSOLE_RECORD
+       default 0x400 if CONSOLE_RECORD
+       help
+         Set the size of the console output buffer. When this fills up, no
+         more data will be recorded until some is removed. The buffer is
+         allocated immediately after the malloc() region is ready.
+
+config CONSOLE_RECORD_IN_SIZE
+       hex "Input buffer size"
+       depends on CONSOLE_RECORD
+       default 0x100 if CONSOLE_RECORD
+       help
+         Set the size of the console input buffer. When this contains data,
+         tstc() and getc() will use this in preference to real device input.
+         The buffer is allocated immediately after the malloc() region is
+         ready.
index 09baa5c5504546b7197666e1f94796b8f2c1d76b..b035c90ff3b7a7fd05c1e4b1f9d832b7faf8dba3 100644 (file)
@@ -737,6 +737,15 @@ static int mark_bootstage(void)
        return 0;
 }
 
+static int initf_console_record(void)
+{
+#if defined(CONFIG_CONSOLE_RECORD) && defined(CONFIG_SYS_MALLOC_F_LEN)
+       return console_record_init();
+#else
+       return 0;
+#endif
+}
+
 static int initf_dm(void)
 {
 #if defined(CONFIG_DM) && defined(CONFIG_SYS_MALLOC_F_LEN)
@@ -773,6 +782,7 @@ static init_fnc_t init_sequence_f[] = {
        trace_early_init,
 #endif
        initf_malloc,
+       initf_console_record,
 #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
        /* TODO: can this go into arch_cpu_init()? */
        probecpu,
index 85aef95a89589c12c634ebeb420e691a073b6699..f7118e8fc486e74c6218762d6902fe07a2cbf413 100644 (file)
@@ -280,6 +280,15 @@ static int initr_malloc(void)
        return 0;
 }
 
+static int initr_console_record(void)
+{
+#if defined(CONFIG_CONSOLE_RECORD)
+       return console_record_init();
+#else
+       return 0;
+#endif
+}
+
 #ifdef CONFIG_SYS_NONCACHED_MEMORY
 static int initr_noncached(void)
 {
@@ -731,6 +740,7 @@ init_fnc_t init_sequence_r[] = {
 #endif
        initr_barrier,
        initr_malloc,
+       initr_console_record,
 #ifdef CONFIG_SYS_NONCACHED_MEMORY
        initr_noncached,
 #endif
index 10972b04a6f6da4980f1ceaea93d1b8f37d0a38a..b3f126cceba6633ef9e49598a81a3a1f54908d29 100644 (file)
@@ -378,6 +378,15 @@ int getc(void)
        if (!gd->have_console)
                return 0;
 
+#ifdef CONFIG_CONSOLE_RECORD
+       if (gd->console_in.start) {
+               int ch;
+
+               ch = membuff_getbyte(&gd->console_in);
+               if (ch != -1)
+                       return 1;
+       }
+#endif
        if (gd->flags & GD_FLG_DEVINIT) {
                /* Get from the standard input */
                return fgetc(stdin);
@@ -396,7 +405,12 @@ int tstc(void)
 
        if (!gd->have_console)
                return 0;
-
+#ifdef CONFIG_CONSOLE_RECORD
+       if (gd->console_in.start) {
+               if (membuff_peekbyte(&gd->console_in) != -1)
+                       return 1;
+       }
+#endif
        if (gd->flags & GD_FLG_DEVINIT) {
                /* Test the standard input */
                return ftstc(stdin);
@@ -470,6 +484,10 @@ void putc(const char c)
                return;
        }
 #endif
+#ifdef CONFIG_CONSOLE_RECORD
+       if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start)
+               membuff_putbyte(&gd->console_out, c);
+#endif
 #ifdef CONFIG_SILENT_CONSOLE
        if (gd->flags & GD_FLG_SILENT)
                return;
@@ -513,6 +531,10 @@ void puts(const char *s)
                return;
        }
 #endif
+#ifdef CONFIG_CONSOLE_RECORD
+       if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start)
+               membuff_put(&gd->console_out, s, strlen(s));
+#endif
 #ifdef CONFIG_SILENT_CONSOLE
        if (gd->flags & GD_FLG_SILENT)
                return;
@@ -575,6 +597,32 @@ int vprintf(const char *fmt, va_list args)
        return i;
 }
 
+#ifdef CONFIG_CONSOLE_RECORD
+int console_record_init(void)
+{
+       int ret;
+
+       ret = membuff_new(&gd->console_out, CONFIG_CONSOLE_RECORD_OUT_SIZE);
+       if (ret)
+               return ret;
+       ret = membuff_new(&gd->console_in, CONFIG_CONSOLE_RECORD_IN_SIZE);
+
+       return ret;
+}
+
+void console_record_reset(void)
+{
+       membuff_purge(&gd->console_out);
+       membuff_purge(&gd->console_in);
+}
+
+void console_record_reset_enable(void)
+{
+       console_record_reset();
+       gd->flags |= GD_FLG_RECORD;
+}
+#endif
+
 /* test if ctrl-c was pressed */
 static int ctrlc_disabled = 0; /* see disable_ctrl() */
 static int ctrlc_was_pressed = 0;
index d0383f3d7693bebbd8e757a5027e7c9fb26a721c..1abdcaa6b7cd3f9f21affd12e941a82b7b135bbf 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #ifndef __ASSEMBLY__
+#include <membuff.h>
 #include <linux/list.h>
 
 typedef struct global_data {
@@ -103,6 +104,10 @@ typedef struct global_data {
 #endif
        struct udevice *cur_serial_dev; /* current serial device */
        struct arch_global_data arch;   /* architecture-specific data */
+#ifdef CONFIG_CONSOLE_RECORD
+       struct membuff console_out;     /* console output */
+       struct membuff console_in;      /* console input */
+#endif
 } gd_t;
 #endif
 
@@ -121,5 +126,6 @@ typedef struct global_data {
 #define GD_FLG_FULL_MALLOC_INIT        0x00200 /* Full malloc() is ready          */
 #define GD_FLG_SPL_INIT                0x00400 /* spl_init() has been called      */
 #define GD_FLG_SKIP_RELOC      0x00800 /* Don't relocate */
+#define GD_FLG_RECORD          0x01000 /* Record console */
 
 #endif /* __ASM_GENERIC_GBL_DATA_H */
index 097518d1503f9431f1cbf01d7d6d50188e5a5b68..3d37f6a53bf71f4698ca601ae9d2ffc8b624b8eb 100644 (file)
@@ -20,6 +20,28 @@ void clear_ctrlc(void);      /* clear the Control-C condition */
 int disable_ctrlc(int);        /* 1 to disable, 0 to enable Control-C detect */
 int confirm_yesno(void);        /*  1 if input is "y", "Y", "yes" or "YES" */
 
+/**
+ * console_record_init() - set up the console recording buffers
+ *
+ * This should be called as soon as malloc() is available so that the maximum
+ * amount of console output can be recorded.
+ */
+int console_record_init(void);
+
+/**
+ * console_record_reset() - reset the console recording buffers
+ *
+ * Removes any data in the buffers
+ */
+void console_record_reset(void);
+
+/**
+ * console_record_reset_enable() - reset and enable the console buffers
+ *
+ * This should be called to enable the console buffer.
+ */
+void console_record_reset_enable(void);
+
 /*
  * CONSOLE multiplexing.
  */