From: Simon Glass <simon.glass@canonical.com> Add err_putsn() to output errors with a specified length, which is more efficient when the length is already known (e.g., from snprintf()). Create console_putsn_select() which uses device putsn() methods when CONFIG_CONSOLE_PUTSN is enabled, falling back to puts() otherwise. Refactor err_puts() to call err_putsn() and update err_printf() to use the length returned by vscnprintf(). Co-developed-by: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- common/console.c | 59 +++++++++++++++++++++++++++++++++++++++-------- include/console.h | 15 ++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/common/console.c b/common/console.c index f9669a0e028..96e8977ce06 100644 --- a/common/console.c +++ b/common/console.c @@ -291,30 +291,56 @@ static void console_putc_pager(int file, const char c) } /** - * console_puts_select() - Output a string to all console devices + * console_putsn_select() - Output a string with length to console devices * * @file: File number to output to (e,g, stdout, see stdio.h) * @serial_only: true to output only to serial, false to output to everything * else * @s: String to output + * @len: Length of string to output */ -static void console_puts_select(int file, bool serial_only, const char *s) +static void console_putsn_select(int file, bool serial_only, const char *s, + int len) { + struct stdio_dev *sdev; int i; struct stdio_dev *dev; for_each_console_dev(i, file, dev) { bool is_serial = console_dev_is_serial(dev); - if (dev->puts && serial_only == is_serial) - dev->puts(dev, s); + if (serial_only == is_serial) { + sdev = dev; + if (CONFIG_IS_ENABLED(CONSOLE_PUTSN) && sdev->putsn) + sdev->putsn(sdev, s, len); + else if (sdev->puts) + sdev->puts(sdev, s); + } } } -void err_puts(bool serial_only, const char *s) +/** + * console_puts_select() - Output a string to all console devices + * + * @file: File number to output to (e,g, stdout, see stdio.h) + * @serial_only: true to output only to serial, false to output to everything + * else + * @s: String to output + */ +static void console_puts_select(int file, bool serial_only, const char *s) +{ + console_putsn_select(file, serial_only, s, strlen(s)); +} + +void err_putsn(bool serial_only, const char *s, int len) { if (gd->flags & GD_FLG_DEVINIT) - console_puts_select(stderr, serial_only, s); + console_putsn_select(stderr, serial_only, s, len); +} + +void err_puts(bool serial_only, const char *s) +{ + err_putsn(serial_only, s, strlen(s)); } int err_printf(bool serial_only, const char *fmt, ...) @@ -330,7 +356,7 @@ int err_printf(bool serial_only, const char *fmt, ...) */ ret = vscnprintf(buf, sizeof(buf), fmt, args); va_end(args); - err_puts(serial_only, buf); + err_putsn(serial_only, buf, ret); return ret; } @@ -472,11 +498,24 @@ static inline void console_putc_pager(int file, const char c) stdio_devices[file]->putc(stdio_devices[file], c); } -void console_puts_select(int file, bool serial_only, const char *s) +static inline void console_putsn_select(int file, bool serial_only, + const char *s, int len) { + struct stdio_dev *sdev; + if ((gd->flags & GD_FLG_DEVINIT) && - serial_only == console_dev_is_serial(stdio_devices[file])) - stdio_devices[file]->puts(stdio_devices[file], s); + serial_only == console_dev_is_serial(stdio_devices[file])) { + sdev = stdio_devices[file]; + if (CONFIG_IS_ENABLED(CONSOLE_PUTSN) && sdev->putsn) + sdev->putsn(sdev, s, len); + else + sdev->puts(sdev, s); + } +} + +void console_puts_select(int file, bool serial_only, const char *s) +{ + console_putsn_select(file, serial_only, s, strlen(s)); } static inline void console_puts_pager(int file, const char *s) diff --git a/include/console.h b/include/console.h index 83b8d4f642c..486131f8bf7 100644 --- a/include/console.h +++ b/include/console.h @@ -158,6 +158,21 @@ static inline bool console_record_isempty(void) */ int console_announce_r(void); +/** + * err_putsn() - Output a string with length to selected console devices + * + * This writes to stderr only. It is useful for outputting errors when the + * length is already known. + * + * Outputs exactly @len characters from @s, regardless of any nul characters. + * + * @serial_only: true to output only to serial, false to output to everything + * else + * @s: String to output (need not be nul-terminated) + * @len: Number of characters to output + */ +void err_putsn(bool serial_only, const char *s, int len); + /** * err_puts() - Output a string to selected console devices * -- 2.43.0