[PATCH v2 00/16] console: Refactor in preparation for the pager

From: Simon Glass <sjg@chromium.org> This series tidies up a few small things the serial and console areas: - Move detection of serial-console size to the serial module - Provide a Kconfig to disable serial detection - Fix some missing driver-model flags in stdio devices - Move console docs into the main documentation This series is marked v2 since some of the patches were sent in any earlier series. With various tweaks that series grew too large to be sent as a single series. Changes in v2: - Add new patch to provide a way to tell if the video is visible - Add new patch to move environment handling lower in the file - Add new patch to refactor handling of the result in on_console() Simon Glass (16): bdinfo: Show the serial device video: Mark the vidconsole as a driver model stdio device video: Mark keyboards as driver model stdio devices serial: Generalise the code to check the terminal size serial: Cache the terminal size sandbox: Add a function to detect terminal connection sandbox: Provide a way to tell if the video is visible post: Include config.h in the header cli: Avoid sending ANSI characters to a non-terminal console: Update coninfo to use sdev instead of dev console: Update conio command to show uclass console: Move environment handling lower in the file console: Refactor handling of the result in on_console() doc: Remove obsolete text in README.console doc: Move console docs to rST doc: Tidy up the console docs a little arch/sandbox/cpu/os.c | 5 + arch/sandbox/cpu/start.c | 4 + arch/sandbox/cpu/state.c | 14 +++ arch/sandbox/include/asm/state.h | 15 +++ cmd/Kconfig | 8 ++ cmd/bdinfo.c | 3 +- cmd/console.c | 45 ++++++--- common/cli.c | 3 +- common/console.c | 130 ++++++++++++------------- doc/README.console | 100 ------------------- doc/usage/console.rst | 62 ++++++++++++ doc/usage/index.rst | 1 + drivers/input/keyboard-uclass.c | 2 +- drivers/serial/Kconfig | 15 +++ drivers/serial/serial-uclass.c | 156 ++++++++++++++++++++++++++++++ drivers/video/vidconsole-uclass.c | 2 +- include/os.h | 8 ++ include/post.h | 2 + include/serial.h | 63 ++++++++++++ include/video.h | 21 ++++ lib/efi_loader/efi_console.c | 124 +----------------------- test/cmd/bdinfo.c | 4 +- 22 files changed, 484 insertions(+), 303 deletions(-) delete mode 100644 doc/README.console create mode 100644 doc/usage/console.rst -- 2.43.0 base-commit: 03cd5e055b153666b836bbc0c3d3b3c7ade52bf0 branch: clia2

From: Simon Glass <sjg@chromium.org> Show the name of the serial device with the 'bdinfo' command. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) cmd/bdinfo.c | 3 ++- test/cmd/bdinfo.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index b0d6663c6df..8208e03a4e2 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -105,7 +105,8 @@ static void print_serial(struct udevice *dev) if (ret) return; - lprint_num_l("serial addr", info.addr); + lprint_str("serial", dev->name); + lprint_num_l(" addr", info.addr); lprint_num_l(" width", info.reg_width); lprint_num_l(" shift", info.reg_shift); lprint_num_l(" offset", info.reg_offset); diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c index 88115a22203..c59823a2e9e 100644 --- a/test/cmd/bdinfo.c +++ b/test/cmd/bdinfo.c @@ -201,7 +201,9 @@ static int bdinfo_test_all(struct unit_test_state *uts) ut_assertnonnull(gd->cur_serial_dev); ut_assertok(serial_getinfo(gd->cur_serial_dev, &info)); - ut_assertok(test_num_l(uts, "serial addr", info.addr)); + ut_assert_nextline("serial = %s", + gd->cur_serial_dev->name); + ut_assertok(test_num_l(uts, " addr", info.addr)); ut_assertok(test_num_l(uts, " width", info.reg_width)); ut_assertok(test_num_l(uts, " shift", info.reg_shift)); ut_assertok(test_num_l(uts, " offset", info.reg_offset)); -- 2.43.0

From: Simon Glass <sjg@chromium.org> Set the DEV_FLAGS_DM flag so this stdio device is recognised as being provided by a driver model device. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) drivers/video/vidconsole-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index f1b2d61bd8f..a98344cf9a7 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -764,7 +764,7 @@ static int vidconsole_post_probe(struct udevice *dev) strcpy(sdev->name, "vidconsole"); } - sdev->flags = DEV_FLAGS_OUTPUT; + sdev->flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_DM; sdev->putc = vidconsole_putc; sdev->puts = vidconsole_puts; sdev->priv = dev; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Set the DEV_FLAGS_DM flag so keybaords are recognised as being provided by a driver model device. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) drivers/input/keyboard-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard-uclass.c b/drivers/input/keyboard-uclass.c index df9ee8f7d65..dabf0d2e0bd 100644 --- a/drivers/input/keyboard-uclass.c +++ b/drivers/input/keyboard-uclass.c @@ -68,7 +68,7 @@ static int keyboard_pre_probe(struct udevice *dev) int ret; strlcpy(sdev->name, dev->name, sizeof(sdev->name)); - sdev->flags = DEV_FLAGS_INPUT; + sdev->flags = DEV_FLAGS_INPUT | DEV_FLAGS_DM; sdev->getc = keyboard_getc; sdev->tstc = keyboard_tstc; sdev->start = keyboard_start; -- 2.43.0

From: Simon Glass <sjg@chromium.org> The EFI loader has some code to check the size (rows and columns) of an attached terminal. Move this over to the serial uclass so that it can be used elsewhere. Create a new CONFIG_SERIAL_TERM_PRESENT to control whether it should be used. Enable that for the EFI loader to preserve existing behaviour. Adjust the implementation so that it returns a useful error code on failure. Put the ESC and cESC values in the serial.h header. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) drivers/serial/Kconfig | 15 ++++ drivers/serial/serial-uclass.c | 118 +++++++++++++++++++++++++++++++ include/serial.h | 18 +++++ lib/efi_loader/efi_console.c | 124 +-------------------------------- 4 files changed, 154 insertions(+), 121 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d58152abc7f..7d27dad327d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -202,6 +202,21 @@ config VPL_DM_SERIAL implements serial_putc() etc. The uclass interface is defined in include/serial.h. +config SERIAL_TERM_PRESENT + bool "Assume there is a serial terminal present on the serial line" + depends on DM_SERIAL + default y if EFI_LOADER + help + In some cases boards are connected to a serial terminal and it is + useful to emit ANSI codes or other characters to determine the + properties of the terminal. + + Enable this if you wish to have these features. + + Note that enabling this for a board which is sending its output to + a log will result in junk in the log. It also introduces a delay of + up to 100ms on startup. + config DEBUG_UART bool "Enable an early debug UART for debugging" help diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index a08678dde4e..1204fb5d4c4 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -13,6 +13,7 @@ #include <os.h> #include <serial.h> #include <stdio_dev.h> +#include <time.h> #include <watchdog.h> #include <asm/global_data.h> #include <dm/lists.h> @@ -557,6 +558,123 @@ static int on_baudrate(const char *name, const char *value, enum env_op op, } U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); +/** + * term_get_char() - read a character from the console + * + * Wait for up to 100 ms to read a character from the console. + * + * @c: pointer to the buffer to receive the character + * Return: 0 on success, -ETIMEDOUT if timed out + */ +static int term_get_char(s32 *c) +{ + u64 timeout; + + /* Wait up to 100 ms for a character */ + timeout = timer_get_us() + 100000; + + while (!tstc()) + if (timer_get_us() > timeout) + return -ETIMEDOUT; + + *c = getchar(); + + return 0; +} + +/** + * term_read_reply() - receive and parse a reply from the terminal + * + * @n: array of return values + * @num: number of return values expected + * @end_char: character indicating end of terminal message + * Return: non-zero indicates error + */ +static int term_read_reply(int *n, int num, char end_char) +{ + int ret, i = 0; + s32 c; + + ret = term_get_char(&c); + if (ret) + return ret; + if (c != cESC) + return -EPROTO; + + ret = term_get_char(&c); + if (ret) + return ret; + if (c != '[') + return -EPROTO; + + n[0] = 0; + while (1) { + int ret; + + ret = term_get_char(&c); + if (ret) + return ret; + + if (c == ';') { + i++; + if (i >= num) + return -EPROTO; + n[i] = 0; + continue; + } else if (c == end_char) { + break; + } else if (c > '9' || c < '0') { + return -EPROTO; + } + + /* Read one more decimal position */ + n[i] *= 10; + n[i] += c - '0'; + } + if (i != num - 1) + return -EPROTO; + + return 0; +} + +int serial_query_size(int *rowsp, int *colsp) +{ + int ret = 0; + int n[2]; + + if (!CONFIG_IS_ENABLED(SERIAL_TERM_PRESENT)) + return -ENOENT; + + /* Empty input buffer */ + while (tstc()) + getchar(); + + /* + * Not all terminals understand CSI [18t for querying the console size. + * We should adhere to escape sequences documented in the console_codes + * man page and the ECMA-48 standard. + * + * So here we follow a different approach. We position the cursor to the + * bottom right and query its position. Before leaving the function we + * restore the original cursor position. + */ + puts(ESC "7" /* Save cursor position */ + ESC "[r" /* Set scrolling region to full window */ + ESC "[999;999H" /* Move to bottom right corner */ + ESC "[6n"); /* Query cursor position */ + + /* Read {rows,cols} */ + ret = term_read_reply(n, 2, 'R'); + if (!ret) { + *colsp = n[1]; + *rowsp = n[0]; + } + + printf(ESC "8"); /* Restore cursor position */ + + return ret; +} + #if CONFIG_IS_ENABLED(SERIAL_PRESENT) static int serial_post_probe(struct udevice *dev) { diff --git a/include/serial.h b/include/serial.h index e5f6d984d28..2aba4c313c2 100644 --- a/include/serial.h +++ b/include/serial.h @@ -3,6 +3,10 @@ #include <post.h> +/* Escape value */ +#define cESC '\x1b' +#define ESC "\x1b" + struct serial_device { /* enough bytes to match alignment of following func pointer */ char name[16]; @@ -382,4 +386,18 @@ static inline void serial_flush(void) {} int serial_getc(void); int serial_tstc(void); +/** + * serial_query_size() - query serial console size + * + * When using a serial console or the net console we can only devise the + * terminal size by querying the terminal using ECMA-48 control sequences. + * + * @rowsp: returns number of rows + * @colsp: returns number of columns + * Returns: 0 on success, -NOENT if no terminal is present, -ETIMEDOUT if we + * checked for a terminal but didn't get a response in time, -EPROTO if the + * terminal did not respond as expected + */ +int serial_query_size(int *rowsp, int *colsp); + #endif diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index ade44cb6e36..d2eabfdb07e 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -16,6 +16,7 @@ #include <efi_loader.h> #include <env.h> #include <log.h> +#include <serial.h> #include <stdio_dev.h> #include <video_console.h> #include <linux/delay.h> @@ -59,9 +60,6 @@ const efi_guid_t efi_guid_text_input_protocol = const efi_guid_t efi_guid_text_output_protocol = EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID; -#define cESC '\x1b' -#define ESC "\x1b" - /* * efi_con_mode - mode information of the Simple Text Output Protocol * @@ -77,76 +75,6 @@ static struct simple_text_output_mode efi_con_mode = { .cursor_visible = 1, }; -/** - * term_get_char() - read a character from the console - * - * Wait for up to 100 ms to read a character from the console. - * - * @c: pointer to the buffer to receive the character - * Return: 0 on success, 1 otherwise - */ -static int term_get_char(s32 *c) -{ - u64 timeout; - - /* Wait up to 100 ms for a character */ - timeout = timer_get_us() + 100000; - - while (!tstc()) - if (timer_get_us() > timeout) - return 1; - - *c = getchar(); - return 0; -} - -/** - * term_read_reply() - receive and parse a reply from the terminal - * - * @n: array of return values - * @num: number of return values expected - * @end_char: character indicating end of terminal message - * Return: non-zero indicates error - */ -static int term_read_reply(int *n, int num, char end_char) -{ - s32 c; - int i = 0; - - if (term_get_char(&c) || c != cESC) - return -1; - - if (term_get_char(&c) || c != '[') - return -1; - - n[0] = 0; - while (1) { - if (!term_get_char(&c)) { - if (c == ';') { - i++; - if (i >= num) - return -1; - n[i] = 0; - continue; - } else if (c == end_char) { - break; - } else if (c > '9' || c < '0') { - return -1; - } - - /* Read one more decimal position */ - n[i] *= 10; - n[i] += c - '0'; - } else { - return -1; - } - } - if (i != num - 1) - return -1; - - return 0; -} - /** * efi_cout_output_string() - write Unicode string to console * @@ -272,52 +200,6 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols) return (mode->rows == rows) && (mode->columns == cols); } -/** - * query_console_serial() - query serial console size - * - * When using a serial console or the net console we can only devise the - * terminal size by querying the terminal using ECMA-48 control sequences. - * - * @rows: pointer to return number of rows - * @cols: pointer to return number of columns - * Returns: 0 on success - */ -static int query_console_serial(int *rows, int *cols) -{ - int ret = 0; - int n[2]; - - /* Empty input buffer */ - while (tstc()) - getchar(); - - /* - * Not all terminals understand CSI [18t for querying the console size. - * We should adhere to escape sequences documented in the console_codes - * man page and the ECMA-48 standard. - * - * So here we follow a different approach. We position the cursor to the - * bottom right and query its position. Before leaving the function we - * restore the original cursor position. - */ - printf(ESC "7" /* Save cursor position */ - ESC "[r" /* Set scrolling region to full window */ - ESC "[999;999H" /* Move to bottom right corner */ - ESC "[6n"); /* Query cursor position */ - - /* Read {rows,cols} */ - if (term_read_reply(n, 2, 'R')) { - ret = 1; - goto out; - } - - *cols = n[1]; - *rows = n[0]; -out: - printf(ESC "8"); /* Restore cursor position */ - return ret; -} - /** * query_vidconsole() - query video console size * @@ -363,8 +245,8 @@ void efi_setup_console_size(void) if (IS_ENABLED(CONFIG_VIDEO)) ret = query_vidconsole(&rows, &cols); - if (ret) - ret = query_console_serial(&rows, &cols); + if (ret && IS_ENABLED(CONFIG_DM_SERIAL)) + ret = serial_query_size(&rows, &cols); if (ret) return; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add serial_priv structure to serial uclass to cache terminal dimensions. When serial_query_size() successfully queries the terminal, store the results in the uclass-private data for later retrieval. This avoids repeated terminal queries and improves performance when different subsystems need the terminal size. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) drivers/serial/serial-uclass.c | 38 ++++++++++++++++++++++++++++++++++ include/serial.h | 24 +++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 1204fb5d4c4..27de461d196 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -24,6 +24,8 @@ DECLARE_GLOBAL_DATA_PTR; +#define ESC "\x1b" + /* * Table with supported baudrates (defined in config_xyz.h) */ @@ -666,8 +668,18 @@ int serial_query_size(int *rowsp, int *colsp) /* Read {rows,cols} */ ret = term_read_reply(n, 2, 'R'); if (!ret) { + struct serial_priv *priv; + struct uclass *uc; + *colsp = n[1]; *rowsp = n[0]; + + /* Store in serial uclass private data if available */ + if (!uclass_get(UCLASS_SERIAL, &uc)) { + priv = uclass_get_priv(uc); + priv->rows = n[0]; + priv->cols = n[1]; + } } printf(ESC "8"); /* Restore cursor position */ @@ -675,6 +687,31 @@ int serial_query_size(int *rowsp, int *colsp) return ret; } +int serial_get_size(struct udevice *dev, int *rowsp, int *colsp) +{ + struct serial_priv *priv; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_SERIAL, &uc); + if (ret) + return ret; + + priv = uclass_get_priv(uc); + + /* Check if we have cached values */ + if (priv->rows && priv->cols) { + *rowsp = priv->rows; + *colsp = priv->cols; + return 0; + } + + /* No cached values, query the terminal */ + ret = serial_query_size(rowsp, colsp); + + return ret; +} + #if CONFIG_IS_ENABLED(SERIAL_PRESENT) static int serial_post_probe(struct udevice *dev) { @@ -730,5 +767,6 @@ UCLASS_DRIVER(serial) = { .post_probe = serial_post_probe, .pre_remove = serial_pre_remove, .per_device_auto = sizeof(struct serial_dev_priv), + .priv_auto = sizeof(struct serial_priv), }; #endif diff --git a/include/serial.h b/include/serial.h index 2aba4c313c2..9ed3793b647 100644 --- a/include/serial.h +++ b/include/serial.h @@ -291,6 +291,17 @@ struct dm_serial_ops { int (*getinfo)(struct udevice *dev, struct serial_device_info *info); }; +/** + * struct serial_priv - private data for serial uclass + * + * @rows: Number of terminal rows (0 if unknown) + * @cols: Number of terminal columns (0 if unknown) + */ +struct serial_priv { + int rows; + int cols; +}; + /** * struct serial_dev_priv - information about a device used by the uclass * @@ -400,4 +411,17 @@ int serial_tstc(void); */ int serial_query_size(int *rowsp, int *colsp); +/** + * serial_get_size() - get serial console size + * + * Get the terminal size, using cached values if available, or failing that, + * query the terminal + * + * @dev: serial device to query (may be NULL) + * @rowsp: returns number of rows + * @colsp: returns number of columns + * Returns: 0 on success, -ve on error + */ +int serial_get_size(struct udevice *dev, int *rowsp, int *colsp); + #endif -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add a serial_is_tty() function that determines if the serial console is connected to a terminal. For sandbox, this uses os_isatty() to check stdin, except for cooked mode, where we don't want to assume anything about the terminal. For other platforms, it always returns true. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) arch/sandbox/cpu/os.c | 5 +++++ arch/sandbox/cpu/start.c | 4 ++++ arch/sandbox/cpu/state.c | 7 +++++++ arch/sandbox/include/asm/state.h | 8 ++++++++ include/os.h | 8 ++++++++ include/serial.h | 21 +++++++++++++++++++++ 6 files changed, 53 insertions(+) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index c19f859d4e0..101d695a556 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -142,6 +142,11 @@ int os_close(int fd) return -1; } +int os_isatty(int fd) +{ + return isatty(fd); +} + int os_unlink(const char *pathname) { return unlink(pathname); diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index e4e4932c183..02d16bfe930 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -613,6 +613,10 @@ int sandbox_main(int argc, char *argv[]) if (os_parse_args(state, argc, argv)) return 1; + /* Detect if serial console is connected to a terminal */ + state->serial_is_tty = os_isatty(1) && + state->term_raw != STATE_TERM_COOKED; + if (state->ram_buf_fname) { ret = os_read_ram_buf(state->ram_buf_fname); if (ret) { diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index 949ca42de94..d883cf2132a 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -476,6 +476,13 @@ bool sandbox_sf_bootdev_enabled(void) return !state->disable_sf_bootdevs; } +bool sandbox_serial_is_tty(void) +{ + struct sandbox_state *state = state_get_current(); + + return state->serial_is_tty; +} + int state_init(void) { state = &main_state; diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 3aa35c112be..5350ee6b8fa 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -157,6 +157,7 @@ struct sandbox_state { bool ignore_missing_state_on_read; /* No error if state missing */ bool show_lcd; /* Show LCD on start-up */ bool double_lcd; /* Double display size for high-DPI */ + bool serial_is_tty; /* Serial console is connected to a tty */ enum sysreset_t last_sysreset; /* Last system reset type */ bool sysreset_allowed[SYSRESET_COUNT]; /* Allowed system reset types */ enum state_terminal_raw term_raw; /* Terminal raw/cooked */ @@ -377,6 +378,13 @@ int state_get_rel_filename(const char *rel_path, char *buf, int size); */ int state_load_other_fdt(const char **bufp, int *sizep); +/** + * sandbox_serial_is_tty() - check if serial console is connected to a tty + * + * Return: true if serial console is connected to a terminal, false if not + */ +bool sandbox_serial_is_tty(void); + /** * Initialize the test system state */ diff --git a/include/os.h b/include/os.h index 35757fc8bb8..3393acb435a 100644 --- a/include/os.h +++ b/include/os.h @@ -90,6 +90,14 @@ int os_open(const char *pathname, int flags); */ int os_close(int fd); +/** + * os_isatty() - check if file descriptor refers to a terminal + * + * @fd: File descriptor to check + * Return: 1 if fd is a terminal, 0 if not, -1 on error + */ +int os_isatty(int fd); + /** * os_unlink() - access to the OS unlink() system call * diff --git a/include/serial.h b/include/serial.h index 9ed3793b647..02c28f8605c 100644 --- a/include/serial.h +++ b/include/serial.h @@ -2,6 +2,9 @@ #define __SERIAL_H__ #include <post.h> +#ifdef CONFIG_SANDBOX +#include <asm/state.h> +#endif /* Escape value */ #define cESC '\x1b' @@ -424,4 +427,22 @@ int serial_query_size(int *rowsp, int *colsp); */ int serial_get_size(struct udevice *dev, int *rowsp, int *colsp); +/* + * serial_is_tty() - check if the serial console is connected to a terminal + * + * This does not indicate that there is actually a terminal, only that if there + * is one, we can assume it is present and connected + * + * Return: true if any serial console is likely connected to a terminal, false if not + */ +static inline bool serial_is_tty(void) +{ +#ifdef CONFIG_SANDBOX + return sandbox_serial_is_tty(); +#else + /* assume that it is! */ + return true; +#endif +} + #endif -- 2.43.0

From: Simon Glass <sjg@chromium.org> Sandbox is often run with the display disabled, so even though it has a video device, it is not being shown. Provide a way to detect this. For all other platforms, we assume the display is shown, when there is a video device. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Add new patch to provide a way to tell if the video is visible arch/sandbox/cpu/state.c | 7 +++++++ arch/sandbox/include/asm/state.h | 7 +++++++ include/video.h | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index d883cf2132a..e492855755b 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -483,6 +483,13 @@ bool sandbox_serial_is_tty(void) return state->serial_is_tty; } +bool sandbox_video_is_visible(void) +{ + struct sandbox_state *state = state_get_current(); + + return state->show_lcd; +} + int state_init(void) { state = &main_state; diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 5350ee6b8fa..a9c4c889bd9 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -385,6 +385,13 @@ int state_load_other_fdt(const char **bufp, int *sizep); */ bool sandbox_serial_is_tty(void); +/* + * sandbox_video_is_visible() - check if video display is showing + * + * Return: true if display is active, false if just using the serial console + */ +bool sandbox_video_is_visible(void); + /** * Initialize the test system state */ diff --git a/include/video.h b/include/video.h index 5b539eafb89..b2eaecf5866 100644 --- a/include/video.h +++ b/include/video.h @@ -8,6 +8,9 @@ #define _VIDEO_H_ #include <stdio_dev.h> +#ifdef CONFIG_SANDBOX +#include <asm/state.h> +#endif struct udevice; @@ -460,4 +463,22 @@ int video_reserve_from_bloblist(struct video_handoff *ho); */ ulong video_get_fb(void); +/** + * video_is_visible() - check if the video display is being used + * + * This does not indicate that there is actually a display, only that if there + * is one, we can assume it is present + * + * Return: true if any display is likely visible, false if not + */ +static inline bool video_is_visible(void) +{ +#ifdef CONFIG_SANDBOX + return sandbox_video_is_visible(); +#else + /* assume that it is! */ + return true; +#endif +} + #endif -- 2.43.0

From: Simon Glass <sjg@chromium.org> The post system requires use of CFG_xxx values which are only included via the config.h header. Most files don't include this now. The serial.h header includes post.h which causes a build error on any platform which enables CONFIG_POST, such as pg_wcom_seli8 Add an explicit #include of config.h in the post.h header file. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) include/post.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/post.h b/include/post.h index da851e37fa2..74039e56e29 100644 --- a/include/post.h +++ b/include/post.h @@ -15,6 +15,8 @@ #if defined(CONFIG_POST) +#include <config.h> + #ifndef CFG_POST_EXTERNAL_WORD_FUNCS #ifdef CFG_SYS_POST_WORD_ADDR #define _POST_WORD_ADDR CFG_SYS_POST_WORD_ADDR -- 2.43.0

From: Simon Glass <sjg@chromium.org> Detect if there is no terminal present (this only works on sandbox) and skip sending ANSI characters when the CLI starts up. This avoids having them in logs, for example. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) common/cli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/cli.c b/common/cli.c index 4694a35cd0e..23988330dd8 100644 --- a/common/cli.c +++ b/common/cli.c @@ -20,6 +20,7 @@ #include <fdtdec.h> #include <hang.h> #include <malloc.h> +#include <serial.h> #include <asm/global_data.h> #include <dm/ofnode.h> #include <linux/errno.h> @@ -337,6 +338,6 @@ void cli_init(void) hush_init_var(); #endif - if (CONFIG_IS_ENABLED(VIDEO_ANSI)) + if (CONFIG_IS_ENABLED(VIDEO_ANSI) && serial_is_tty()) printf(ANSI_CURSOR_SHOW "\n"); } -- 2.43.0

From: Simon Glass <sjg@chromium.org> The 'dev' variable is generally used for driver model, so change do_coninfo() to use sdev, to avoid confusion. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) cmd/console.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cmd/console.c b/cmd/console.c index a8133ee3fa3..cb0c041d947 100644 --- a/cmd/console.c +++ b/cmd/console.c @@ -11,34 +11,33 @@ #include <iomux.h> #include <stdio_dev.h> -extern void _do_coninfo (void); static int do_coninfo(struct cmd_tbl *cmd, int flag, int argc, char *const argv[]) { int l; struct list_head *list = stdio_get_list(); struct list_head *pos; - struct stdio_dev *dev; + struct stdio_dev *sdev; /* Scan for valid output and input devices */ puts("List of available devices\n"); list_for_each(pos, list) { - dev = list_entry(pos, struct stdio_dev, list); + sdev = list_entry(pos, struct stdio_dev, list); printf("|-- %s (%s%s)\n", - dev->name, - (dev->flags & DEV_FLAGS_INPUT) ? "I" : "", - (dev->flags & DEV_FLAGS_OUTPUT) ? "O" : ""); + sdev->name, + (sdev->flags & DEV_FLAGS_INPUT) ? "I" : "", + (sdev->flags & DEV_FLAGS_OUTPUT) ? "O" : ""); for (l = 0; l < MAX_FILES; l++) { if (CONFIG_IS_ENABLED(CONSOLE_MUX)) { if (iomux_match_device(console_devices[l], - cd_count[l], dev) >= 0) + cd_count[l], sdev) >= 0) printf("| |-- %s\n", stdio_names[l]); } else { - if (stdio_devices[l] == dev) + if (stdio_devices[l] == sdev) printf("| |-- %s\n", stdio_names[l]); } -- 2.43.0

From: Simon Glass <sjg@chromium.org> When an stdio device is provided by a driver model device, optionally show the uclass. Be careful to avoid increasing code size, since this is a common command. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) cmd/Kconfig | 8 ++++++++ cmd/console.c | 30 ++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index 882a4ee02e3..99101ff6c82 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -175,6 +175,14 @@ config CMD_CONSOLE help Print console devices and information. +config CMD_CONSOLE_EXTRA + bool "Show uclass for driver model devices" + default y if SANDBOX + help + Expands the coninfo command to show the uclass for all stdio devices + which are provided by a driver model device. This increase code size + by about 200 bytes. + config CMD_CPU bool "cpu" depends on CPU diff --git a/cmd/console.c b/cmd/console.c index cb0c041d947..a9940467dbd 100644 --- a/cmd/console.c +++ b/cmd/console.c @@ -8,9 +8,17 @@ * Boot support */ #include <command.h> +#include <dm.h> #include <iomux.h> #include <stdio_dev.h> +/* shenangans to avoid code-size increase */ +#ifdef CONFIG_CMD_CONSOLE_EXTRA +#define USE_NL "" +#else +#define USE_NL "\n" +#endif + static int do_coninfo(struct cmd_tbl *cmd, int flag, int argc, char *const argv[]) { @@ -20,17 +28,32 @@ static int do_coninfo(struct cmd_tbl *cmd, int flag, int argc, struct stdio_dev *sdev; /* Scan for valid output and input devices */ - - puts("List of available devices\n"); + puts("List of available devices\n\n"); + if (IS_ENABLED(CONFIG_CMD_CONSOLE_EXTRA)) + puts("Device File Uclass\n"); list_for_each(pos, list) { sdev = list_entry(pos, struct stdio_dev, list); - printf("|-- %s (%s%s)\n", + printf("|-- %s (%s%s)" USE_NL, sdev->name, (sdev->flags & DEV_FLAGS_INPUT) ? "I" : "", (sdev->flags & DEV_FLAGS_OUTPUT) ? "O" : ""); + if (IS_ENABLED(CONFIG_CMD_CONSOLE_EXTRA) && + IS_ENABLED(CONFIG_DM_STDIO) && + (sdev->flags & DEV_FLAGS_DM)) { + struct udevice *dev = sdev->priv; + int len = 0; + + len += (sdev->flags & DEV_FLAGS_INPUT) != 0; + len += (sdev->flags & DEV_FLAGS_OUTPUT) != 0; + printf("%*s%s", 20 - len - (int)strlen(sdev->name), "", + dev_get_uclass_name(dev)); + } + if (IS_ENABLED(CONFIG_CMD_CONSOLE_EXTRA)) + puts("\n"); + for (l = 0; l < MAX_FILES; l++) { if (CONFIG_IS_ENABLED(CONSOLE_MUX)) { if (iomux_match_device(console_devices[l], @@ -40,7 +63,6 @@ static int do_coninfo(struct cmd_tbl *cmd, int flag, int argc, if (stdio_devices[l] == sdev) printf("| |-- %s\n", stdio_names[l]); } - } } return 0; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Move the environment callbacks lower so that we can call functions elsewhere in common/console.c Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Add new patch to move environment handling lower in the file common/console.c | 130 +++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/common/console.c b/common/console.c index c6dfed6e201..51f646d9fd4 100644 --- a/common/console.c +++ b/common/console.c @@ -29,71 +29,6 @@ DECLARE_GLOBAL_DATA_PTR; #define CSI "\x1b[" -static int on_console(const char *name, const char *value, enum env_op op, - int flags) -{ - int console = -1; - - /* Check for console redirection */ - if (strcmp(name, "stdin") == 0) - console = stdin; - else if (strcmp(name, "stdout") == 0) - console = stdout; - else if (strcmp(name, "stderr") == 0) - console = stderr; - - /* if not actually setting a console variable, we don't care */ - if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0) - return 0; - - switch (op) { - case env_op_create: - case env_op_overwrite: - - if (CONFIG_IS_ENABLED(CONSOLE_MUX)) { - if (iomux_doenv(console, value)) - return 1; - } else { - /* Try assigning specified device */ - if (console_assign(console, value) < 0) - return 1; - } - - return 0; - - case env_op_delete: - if ((flags & H_FORCE) == 0) - printf("Can't delete \"%s\"\n", name); - return 1; - - default: - return 0; - } -} -U_BOOT_ENV_CALLBACK(console, on_console); - -#ifdef CONFIG_SILENT_CONSOLE -static int on_silent(const char *name, const char *value, enum env_op op, - int flags) -{ - if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET)) - if (flags & H_INTERACTIVE) - return 0; - - if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC)) - if ((flags & H_INTERACTIVE) == 0) - return 0; - - if (value != NULL) - gd->flags |= GD_FLG_SILENT; - else - gd->flags &= ~GD_FLG_SILENT; - - return 0; -} -U_BOOT_ENV_CALLBACK(silent, on_silent); -#endif - #ifdef CONFIG_CONSOLE_RECORD /* helper function: access to gd->console_out and gd->console_in */ static void console_record_putc(const char c) @@ -1101,6 +1036,71 @@ static void stdio_print_current_devices(void) printf("%s\n", stderrname); } +static int on_console(const char *name, const char *value, enum env_op op, + int flags) +{ + int console = -1; + + /* Check for console redirection */ + if (strcmp(name, "stdin") == 0) + console = stdin; + else if (strcmp(name, "stdout") == 0) + console = stdout; + else if (strcmp(name, "stderr") == 0) + console = stderr; + + /* if not actually setting a console variable, we don't care */ + if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0) + return 0; + + switch (op) { + case env_op_create: + case env_op_overwrite: + + if (CONFIG_IS_ENABLED(CONSOLE_MUX)) { + if (iomux_doenv(console, value)) + return 1; + } else { + /* Try assigning specified device */ + if (console_assign(console, value) < 0) + return 1; + } + + return 0; + + case env_op_delete: + if ((flags & H_FORCE) == 0) + printf("Can't delete \"%s\"\n", name); + return 1; + + default: + return 0; + } +} +U_BOOT_ENV_CALLBACK(console, on_console); + +#ifdef CONFIG_SILENT_CONSOLE +static int on_silent(const char *name, const char *value, enum env_op op, + int flags) +{ + if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET)) + if (flags & H_INTERACTIVE) + return 0; + + if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC)) + if ((flags & H_INTERACTIVE) == 0) + return 0; + + if (value) + gd->flags |= GD_FLG_SILENT; + else + gd->flags &= ~GD_FLG_SILENT; + + return 0; +} +U_BOOT_ENV_CALLBACK(silent, on_silent); +#endif + #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) /* Called after the relocation - use desired console functions */ int console_init_r(void) -- 2.43.0

From: Simon Glass <sjg@chromium.org> This function has lots of return statements in a switch statement. Move them out so we can (later) do something else in this function. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Add new patch to refactor handling of the result in on_console() common/console.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/common/console.c b/common/console.c index 51f646d9fd4..e986fa0f3e5 100644 --- a/common/console.c +++ b/common/console.c @@ -1040,6 +1040,7 @@ static int on_console(const char *name, const char *value, enum env_op op, int flags) { int console = -1; + int result = 0; /* Check for console redirection */ if (strcmp(name, "stdin") == 0) @@ -1056,26 +1057,25 @@ static int on_console(const char *name, const char *value, enum env_op op, switch (op) { case env_op_create: case env_op_overwrite: - if (CONFIG_IS_ENABLED(CONSOLE_MUX)) { if (iomux_doenv(console, value)) - return 1; + result = 1; } else { /* Try assigning specified device */ if (console_assign(console, value) < 0) - return 1; + result = 1; } - - return 0; - + break; case env_op_delete: if ((flags & H_FORCE) == 0) printf("Can't delete \"%s\"\n", name); - return 1; - + result = 1; + break; default: - return 0; + break; } + + return result; } U_BOOT_ENV_CALLBACK(console, on_console); -- 2.43.0

From: Simon Glass <sjg@chromium.org> The latter part of this file is very out-of-date, so drop it. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) doc/README.console | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/doc/README.console b/doc/README.console index 9f5812c89d1..debef45760d 100644 --- a/doc/README.console +++ b/doc/README.console @@ -58,43 +58,3 @@ You can use the following functions to access the console: Remember that all FILE-related functions CANNOT be used before U-Boot relocation (done in 'board_init_r' in arch/*/lib/board.c). - -HOW CAN I USE STANDARD FILE INTO APPLICATIONS? ----------------------------------------------- - -Use the 'bd_mon_fnc' field of the bd_info structure passed to the -application to do everything you want with the console. - -But REMEMBER that that will work only if you have not overwritten any -U-Boot code while loading (or uncompressing) the image of your -application. - -For example, you won't get the console stuff running in the Linux -kernel because the kernel overwrites U-Boot before running. Only -some parameters like the framebuffer descriptors are passed to the -kernel in the high memory area to let the applications (the kernel) -use the framebuffers initialized by U-Boot. - -SUPPORTED DRIVERS ------------------ - -Working drivers: - - serial (architecture dependent serial stuff) - video (mpc8xx video controller) - -Work in progress: - - wl_kbd (Wireless 4PPM keyboard) - -Waiting for volounteers: - - lcd (mpc8xx lcd controller; to ) - -TESTED CONFIGURATIONS ---------------------- - -The driver has been tested with the following configurations (see -CREDITS for other contact informations): - -- MPC823FADS with AD7176 on a PAL TV (YCbYCr) - arsenio@tin.it -- 2.43.0

From: Simon Glass <sjg@chromium.org> Move the console readme into the main documentation, with as few changes as possible. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) doc/{README.console => usage/console.rst} | 13 ++++++------- doc/usage/index.rst | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) rename doc/{README.console => usage/console.rst} (87%) diff --git a/doc/README.console b/doc/usage/console.rst similarity index 87% rename from doc/README.console rename to doc/usage/console.rst index debef45760d..f624cc58038 100644 --- a/doc/README.console +++ b/doc/usage/console.rst @@ -1,11 +1,10 @@ -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+ +.. sectionauthor:: Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it +.. (C) Copyright 2000 +======================= U-Boot console handling -======================== +======================= HOW THE CONSOLE WORKS? ---------------------- @@ -57,4 +56,4 @@ You can use the following functions to access the console: fgetc (like getc but redirected to a file) Remember that all FILE-related functions CANNOT be used before -U-Boot relocation (done in 'board_init_r' in arch/*/lib/board.c). +U-Boot relocation (done in 'board_init_r' in `arch/*/lib/board.c`). diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 20465b8bff6..585aa3f9784 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -6,6 +6,7 @@ Use U-Boot spl_boot blkmap + console dfu environment fdt_overlays -- 2.43.0

From: Simon Glass <sjg@chromium.org> Tweak the documentation to look better when viewed. Use 'write' instead of 'put'. Signed-off-by: Simon Glass <sjg@chromium.org> --- (no changes since v1) doc/usage/console.rst | 69 ++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/doc/usage/console.rst b/doc/usage/console.rst index f624cc58038..d7d41bca187 100644 --- a/doc/usage/console.rst +++ b/doc/usage/console.rst @@ -6,10 +6,10 @@ U-Boot console handling ======================= -HOW THE CONSOLE WORKS? ----------------------- +Introduction +------------ -At system startup U-Boot initializes a serial console. When U-Boot +At system-startup U-Boot initializes a serial console. When U-Boot relocates itself to RAM, all console drivers are initialized (they will register all detected console devices to the system for further use). @@ -17,43 +17,46 @@ use). If not defined in the environment, the first input device is assigned to the 'stdin' file, the first output one to 'stdout' and 'stderr'. -You can use the command "coninfo" to see all registered console +You can use the command `coninfo` to see all registered console devices and their flags. You can assign a standard file (stdin, stdout or stderr) to any device you see in that list simply by assigning its name to the corresponding environment variable. For -example: +example:: - setenv stdin serial <- To use the serial input - setenv stdout video <- To use the video console + # Use the serial input + setenv stdin serial -Do a simple "saveenv" to save the console settings in the environment + # Use the video console + setenv stdout vidconsole + +Do a simple `saveenv` to save the console settings in the environment and get them working on the next startup, too. -HOW CAN I USE STANDARD FILE INTO THE SOURCES? ---------------------------------------------- +How to output text to the console +--------------------------------- You can use the following functions to access the console: -* STDOUT: - putc (to put a char to stdout) - puts (to put a string to stdout) - printf (to format and put a string to stdout) - -* STDIN: - tstc (to test for the presence of a char in stdin) - getc (to get a char from stdin) - -* STDERR: - eputc (to put a char to stderr) - eputs (to put a string to stderr) - eprintf (to format and put a string to stderr) - -* FILE (can be 'stdin', 'stdout', 'stderr'): - fputc (like putc but redirected to a file) - fputs (like puts but redirected to a file) - fprintf (like printf but redirected to a file) - ftstc (like tstc but redirected to a file) - fgetc (like getc but redirected to a file) - -Remember that all FILE-related functions CANNOT be used before -U-Boot relocation (done in 'board_init_r' in `arch/*/lib/board.c`). +stdout + - putc() - write a char to stdout + - puts() - write a string to stdout + - printf() - format and write a string to stdout + +stdin + - tstc() - test for the presence of a char in stdin + - getchar() - get a char from stdin + +stderr + - eputc() - write a char to stderr + - eputs() - write a string to stderr + - eprintf() - format and write a string to stderr + +file ('stdin', 'stdout' or 'stderr') + - fputc() - write a char to a file + - fputs() - write a string to a file + - fprintf() - format and write a string to a file + - ftstc() - test for the presence of a char in file + - fgetc() - get a char from a file + +Remember that FILE-related functions CANNOT be used before U-Boot relocation, +which is done in `board_init_r()`. -- 2.43.0
participants (1)
-
Simon Glass