Merge branch '2019-10-28-azure-ci-support'
[oweals/u-boot.git] / common / console.c
index 3167921ec9aedd32c34f5191bc441bdecb3b735f..89b1e9590cad7b9695b1a0322d3b81574a45c26c 100644 (file)
@@ -1,14 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2000
  * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <console.h>
 #include <debug_uart.h>
 #include <dm.h>
+#include <env.h>
 #include <stdarg.h>
 #include <iomux.h>
 #include <malloc.h>
@@ -17,7 +17,7 @@
 #include <serial.h>
 #include <stdio_dev.h>
 #include <exports.h>
-#include <environment.h>
+#include <env_internal.h>
 #include <watchdog.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -68,11 +68,11 @@ U_BOOT_ENV_CALLBACK(console, on_console);
 static int on_silent(const char *name, const char *value, enum env_op op,
        int flags)
 {
-#if !CONFIG_IS_ENABLED(CONFIG_SILENT_CONSOLE_UPDATE_ON_SET)
+#if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET)
        if (flags & H_INTERACTIVE)
                return 0;
 #endif
-#if !CONFIG_IS_ENABLED(CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC)
+#if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC)
        if ((flags & H_INTERACTIVE) == 0)
                return 0;
 #endif
@@ -197,20 +197,21 @@ static int console_tstc(int file)
 {
        int i, ret;
        struct stdio_dev *dev;
+       int prev;
 
-       disable_ctrlc(1);
+       prev = disable_ctrlc(1);
        for (i = 0; i < cd_count[file]; i++) {
                dev = console_devices[file][i];
                if (dev->tstc != NULL) {
                        ret = dev->tstc(dev);
                        if (ret > 0) {
                                tstcdev = dev;
-                               disable_ctrlc(0);
+                               disable_ctrlc(prev);
                                return ret;
                        }
                }
        }
-       disable_ctrlc(0);
+       disable_ctrlc(prev);
 
        return 0;
 }
@@ -311,12 +312,12 @@ int serial_printf(const char *fmt, ...)
 int fgetc(int file)
 {
        if (file < MAX_FILES) {
-#if CONFIG_IS_ENABLED(CONSOLE_MUX)
                /*
                 * Effectively poll for input wherever it may be available.
                 */
                for (;;) {
                        WATCHDOG_RESET();
+#if CONFIG_IS_ENABLED(CONSOLE_MUX)
                        /*
                         * Upper layer may have already called tstc() so
                         * check for that first.
@@ -324,6 +325,10 @@ int fgetc(int file)
                        if (tstcdev != NULL)
                                return console_getc(file);
                        console_tstc(file);
+#else
+                       if (console_tstc(file))
+                               return console_getc(file);
+#endif
 #ifdef CONFIG_WATCHDOG
                        /*
                         * If the watchdog must be rate-limited then it should
@@ -332,9 +337,6 @@ int fgetc(int file)
                         udelay(1);
 #endif
                }
-#else
-               return console_getc(file);
-#endif
        }
 
        return -1;
@@ -450,12 +452,23 @@ static void pre_console_putc(const char c)
        unmap_sysmem(buffer);
 }
 
+static void pre_console_puts(const char *s)
+{
+       while (*s)
+               pre_console_putc(*s++);
+}
+
 static void print_pre_console_buffer(int flushpoint)
 {
        unsigned long in = 0, out = 0;
        char buf_out[CONFIG_PRE_CON_BUF_SZ + 1];
        char *buf_in;
 
+#ifdef CONFIG_SILENT_CONSOLE
+       if (gd->flags & GD_FLG_SILENT)
+               return;
+#endif
+
        buf_in = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
        if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
                in = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ;
@@ -477,11 +490,19 @@ static void print_pre_console_buffer(int flushpoint)
 }
 #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(int flushpoint) {}
 #endif
 
 void putc(const char c)
 {
+#ifdef CONFIG_SANDBOX
+       /* sandbox can send characters to stdout before it has a console */
+       if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+               os_putc(c);
+               return;
+       }
+#endif
 #ifdef CONFIG_DEBUG_UART
        /* if we don't have a console yet, use the debug UART */
        if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
@@ -489,13 +510,18 @@ void putc(const char c)
                return;
        }
 #endif
+       if (!gd)
+               return;
 #ifdef CONFIG_CONSOLE_RECORD
-       if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start)
+       if ((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)
+       if (gd->flags & GD_FLG_SILENT) {
+               if (!(gd->flags & GD_FLG_DEVINIT))
+                       pre_console_putc(c);
                return;
+       }
 #endif
 
 #ifdef CONFIG_DISABLE_CONSOLE
@@ -518,8 +544,53 @@ void putc(const char c)
 
 void puts(const char *s)
 {
-       while (*s)
-               putc(*s++);
+#ifdef CONFIG_SANDBOX
+       /* sandbox can send characters to stdout before it has a console */
+       if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+               os_puts(s);
+               return;
+       }
+#endif
+#ifdef CONFIG_DEBUG_UART
+       if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+               while (*s) {
+                       int ch = *s++;
+
+                       printch(ch);
+               }
+               return;
+       }
+#endif
+       if (!gd)
+               return;
+#ifdef CONFIG_CONSOLE_RECORD
+       if ((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) {
+               if (!(gd->flags & GD_FLG_DEVINIT))
+                       pre_console_puts(s);
+               return;
+       }
+#endif
+
+#ifdef CONFIG_DISABLE_CONSOLE
+       if (gd->flags & GD_FLG_DISABLE_CONSOLE)
+               return;
+#endif
+
+       if (!gd->have_console)
+               return pre_console_puts(s);
+
+       if (gd->flags & GD_FLG_DEVINIT) {
+               /* Send to the standard output */
+               fputs(stdout, s);
+       } else {
+               /* Send directly to the handler */
+               pre_console_puts(s);
+               serial_puts(s);
+       }
 }
 
 #ifdef CONFIG_CONSOLE_RECORD
@@ -553,7 +624,6 @@ static int ctrlc_disabled = 0;      /* see disable_ctrl() */
 static int ctrlc_was_pressed = 0;
 int ctrlc(void)
 {
-#ifndef CONFIG_SANDBOX
        if (!ctrlc_disabled && gd->have_console) {
                if (tstc()) {
                        switch (getc()) {
@@ -565,7 +635,6 @@ int ctrlc(void)
                        }
                }
        }
-#endif
 
        return 0;
 }
@@ -663,14 +732,22 @@ int console_assign(int file, const char *devname)
        return -1;
 }
 
-static void console_update_silent(void)
+/* return true if the 'silent' flag is removed */
+static bool console_update_silent(void)
 {
 #ifdef CONFIG_SILENT_CONSOLE
-       if (env_get("silent") != NULL)
+       if (env_get("silent")) {
                gd->flags |= GD_FLG_SILENT;
-       else
+       } else {
+               unsigned long flags = gd->flags;
+
                gd->flags &= ~GD_FLG_SILENT;
+
+               return !!(flags & GD_FLG_SILENT);
+       }
 #endif
+
+       return false;
 }
 
 int console_announce_r(void)
@@ -735,6 +812,13 @@ int console_init_r(void)
 #if CONFIG_IS_ENABLED(CONSOLE_MUX)
        int iomux_err = 0;
 #endif
+       int flushpoint;
+
+       /* update silent for env loaded from flash (initr_env) */
+       if (console_update_silent())
+               flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
+       else
+               flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
 
        /* set default handlers at first */
        gd->jt->getc  = serial_getc;
@@ -800,7 +884,7 @@ done:
 
 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
        /* set the environment variables (will overwrite previous env settings) */
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < MAX_FILES; i++) {
                env_set(stdio_names[i], stdio_devices[i]->name);
        }
 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
@@ -812,7 +896,7 @@ done:
        if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
                return 0;
 #endif
-       print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL);
+       print_pre_console_buffer(flushpoint);
        return 0;
 }
 
@@ -826,8 +910,13 @@ int console_init_r(void)
        struct list_head *list = stdio_get_list();
        struct list_head *pos;
        struct stdio_dev *dev;
+       int flushpoint;
 
-       console_update_silent();
+       /* update silent for env loaded from flash (initr_env) */
+       if (console_update_silent())
+               flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
+       else
+               flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
 
 #ifdef CONFIG_SPLASH_SCREEN
        /*
@@ -879,7 +968,7 @@ int console_init_r(void)
 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
 
        /* Setting environment variables */
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < MAX_FILES; i++) {
                env_set(stdio_names[i], stdio_devices[i]->name);
        }
 
@@ -890,7 +979,7 @@ int console_init_r(void)
        if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
                return 0;
 #endif
-       print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL);
+       print_pre_console_buffer(flushpoint);
        return 0;
 }