From: Simon Glass <simon.glass@canonical.com> Add an optional putsn() method to struct stdio_dev to allow devices to provide optimised length-based output. The field is added unconditionally but only used when CONFIG_CONSOLE_PUTSN is enabled. Add console_putsn_pager() and fputsn() to route length-based output through console devices. If a device provides a putsn method, it is used; otherwise, the output falls back to calling putc in a loop. Co-developed-by: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- common/console.c | 31 ++++++++++++++++++++++++------- include/stdio_dev.h | 12 ++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/common/console.c b/common/console.c index c058d3d30a2..67d87c6edfa 100644 --- a/common/console.c +++ b/common/console.c @@ -271,6 +271,7 @@ static int console_tstc(int file) } static void console_puts_pager(int file, const char *s); +static void console_putsn_pager(int file, const char *s, int len); static void console_putc_pager(int file, const char c) { @@ -355,18 +356,28 @@ static void console_puts(int file, bool use_pager, const char *s) } } +static void console_putsn_pager(int file, const char *s, int len) +{ + struct stdio_dev *dev; + int i; + + for_each_console_dev(i, file, dev) { + if (dev->putsn) + dev->putsn(dev, s, len); + else if (dev->puts) + dev->puts(dev, s); + else + while (len--) + dev->putc(dev, *s++); + } +} + static void console_puts_pager(int file, const char *s) { if (IS_ENABLED(CONFIG_CONSOLE_PAGER) && gd_pager()) { console_puts(file, true, s); } else { - struct stdio_dev *dev; - int i; - - for_each_console_dev(i, file, dev) { - if (dev->puts != NULL) - dev->puts(dev, s); - } + console_putsn_pager(file, s, strlen(s)); } } @@ -629,6 +640,12 @@ void fputs(int file, const char *s) console_puts_pager(file, s); } +void fputsn(int file, const char *s, int len) +{ + if ((unsigned int)file < MAX_FILES) + console_putsn_pager(file, s, len); +} + #ifdef CONFIG_CONSOLE_FLUSH_SUPPORT void fflush(int file) { diff --git a/include/stdio_dev.h b/include/stdio_dev.h index 4e3c4708f80..2b2334c9918 100644 --- a/include/stdio_dev.h +++ b/include/stdio_dev.h @@ -38,6 +38,18 @@ struct stdio_dev { void (*putc)(struct stdio_dev *dev, const char c); /* To put a string (accelerator) */ void (*puts)(struct stdio_dev *dev, const char *s); + /** + * putsn() - Output a string with specified length + * + * This outputs exactly @len characters from @s, regardless of any nul + * characters that may be present. This is an optional accelerator - if + * NULL, the console will fall back to calling putc() in a loop. + * + * @dev: Device to output to + * @s: String to output (need not be nul-terminated) + * @len: Number of characters to output + */ + void (*putsn)(struct stdio_dev *dev, const char *s, int len); #ifdef CONFIG_CONSOLE_FLUSH_SUPPORT /* To flush output queue */ void (*flush)(struct stdio_dev *dev); -- 2.43.0