* [PATCH 2/7] stddef: implement scoped_var for use in iterators
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
@ 2026-04-13 10:09 ` Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 3/7] console: have for_each_console declare the iterator internally Ahmad Fatoum
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2026-04-13 10:09 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Our various iterator macros depend on a variable being declared
beforehand, which can be error prone as the value after the last
iteration completed may not be stable or even invoke undefined behavior
on access.
To allow restricting lifetime to only the iteration, implement
scoped_var, a macro for scoping a variable definitions to the statement
following it. The implementation is inspired by Linux __scoped_class.
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
include/linux/stddef.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index 88ff6f1733d2..e5e0421fe558 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -139,4 +139,33 @@ typedef unsigned short wchar_t;
#define DECLARE_FLEX_ARRAY(TYPE, NAME) \
__DECLARE_FLEX_ARRAY(TYPE, NAME)
+#define __scoped_var(decl, _label) \
+ for (decl; ; ({ goto _label; })) \
+ if (0) { \
+_label: \
+ break; \
+ } else
+
+/**
+ * scoped_var - declare a variable scoped to the following statement
+ * @type: the full type (e.g. ``struct foo *`` or ``int``)
+ * @name: the variable name to declare
+ *
+ * Declares @name as @type, initialized to 0, whose scope is limited
+ * to the immediately following statement. Works with both pointer and
+ * scalar types. Intended for use with existing loop macros to add scoped
+ * iterator variables without duplicating the loop body.
+ *
+ * Example with a list iterator:
+ *
+ * .. code-block:: c
+ *
+ * scoped_var(struct foo *p)
+ * list_for_each_entry(p, &head, member) {
+ * // use p
+ * }
+ * // p is out of scope here
+ */
+#define scoped_var(decl) __scoped_var(decl, __UNIQUE_ID(label))
+
#endif
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 3/7] console: have for_each_console declare the iterator internally
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 2/7] stddef: implement scoped_var for use in iterators Ahmad Fatoum
@ 2026-04-13 10:09 ` Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 4/7] console: make console_puts and friends accept a console_device Ahmad Fatoum
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2026-04-13 10:09 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Simplify users of the for_each_console macro, by declaring the iterator
variable inside.
No functional change.
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
commands/bfetch.c | 1 -
commands/edit.c | 2 --
common/bootm.c | 1 -
common/console.c | 11 -----------
common/console_common.c | 5 -----
include/console.h | 7 +++++--
lib/term.c | 1 -
7 files changed, 5 insertions(+), 23 deletions(-)
diff --git a/commands/bfetch.c b/commands/bfetch.c
index d9c615f65aca..705edb08461a 100644
--- a/commands/bfetch.c
+++ b/commands/bfetch.c
@@ -290,7 +290,6 @@ static void print_shell_console(unsigned *line)
const char *shell;
struct command *cmd;
struct string_list sl;
- struct console_device *console;
if (IS_ENABLED(CONFIG_SHELL_HUSH))
shell = "Hush";
diff --git a/commands/edit.c b/commands/edit.c
index c7262711d01f..4442543b9acb 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -464,8 +464,6 @@ static int read_modal_key(bool is_modal)
static bool is_efi_console_active(void)
{
- struct console_device *cdev;
-
if (!IS_ENABLED(CONFIG_DRIVER_SERIAL_EFI_STDIO))
return false;
diff --git a/common/bootm.c b/common/bootm.c
index d4a3a232743f..d84e7647b389 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -653,7 +653,6 @@ struct image_data *bootm_boot_prep(const struct bootm_data *bootm_data)
}
if (bootm_earlycon) {
- struct console_device *console;
const char *earlycon = NULL;
for_each_console(console) {
diff --git a/common/console.c b/common/console.c
index 30a72b2bb6d2..d7013e72e358 100644
--- a/common/console.c
+++ b/common/console.c
@@ -257,7 +257,6 @@ void console_set_stdoutpath(struct console_device *cdev, unsigned baudrate)
struct console_device *of_console_by_stdout_path(void)
{
- struct console_device *console;
struct device_node *stdout_np;
stdout_np = of_get_stdoutpath(NULL);
@@ -459,7 +458,6 @@ EXPORT_SYMBOL(console_unregister);
static __maybe_unused int console_activate_all_fallback(void)
{
int activate = CONSOLE_STDIOE;
- struct console_device *cdev;
for_each_console(cdev) {
if (cdev->f_active & (CONSOLE_STDOUT | CONSOLE_STDERR))
@@ -487,7 +485,6 @@ postenvironment_initcall(console_activate_all_fallback);
static int getc_raw(void)
{
- struct console_device *cdev;
int active = 0;
while (1) {
@@ -515,8 +512,6 @@ static int getc_raw(void)
static int tstc_raw(void)
{
- struct console_device *cdev;
-
if (!IS_ALLOWED(SCONFIG_CONSOLE_INPUT))
return 0;
@@ -578,7 +573,6 @@ EXPORT_SYMBOL(tstc);
int console_putc(unsigned int ch, char c)
{
- struct console_device *cdev;
int init = initialized;
bool crlf = c == '\n';
@@ -613,7 +607,6 @@ EXPORT_SYMBOL(console_putc);
int console_puts(unsigned int ch, const char *str)
{
- struct console_device *cdev;
const char *s = str;
int n = 0;
@@ -636,8 +629,6 @@ EXPORT_SYMBOL(console_puts);
void console_putbin(unsigned int ch, const u8 *str, size_t len)
{
- struct console_device *cdev;
-
switch (initialized) {
case CONSOLE_UNINITIALIZED:
console_init_early();
@@ -667,8 +658,6 @@ EXPORT_SYMBOL(console_putbin);
void console_flush(void)
{
- struct console_device *cdev;
-
for_each_console(cdev) {
if (cdev->flush)
cdev->flush(cdev);
diff --git a/common/console_common.c b/common/console_common.c
index e3b49200c538..1d98e4ec1bcc 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -308,8 +308,6 @@ EXPORT_SYMBOL(vprintf);
struct console_device *console_get_by_dev(struct device *dev)
{
- struct console_device *cdev;
-
for_each_console(cdev) {
if (cdev->dev == dev)
return cdev;
@@ -321,8 +319,6 @@ EXPORT_SYMBOL(console_get_by_dev);
struct console_device *console_get_by_name(const char *name)
{
- struct console_device *cdev;
-
for_each_console(cdev) {
if (cdev->devname && !strcmp(cdev->devname, name))
return cdev;
@@ -340,7 +336,6 @@ EXPORT_SYMBOL(console_get_by_name);
*/
struct console_device *console_get_first_interactive(void)
{
- struct console_device *cdev;
const unsigned char active = CONSOLE_STDIN | CONSOLE_STDOUT;
/* if no console input is allows, then we can't have STDIN on any. */
diff --git a/include/console.h b/include/console.h
index 353a5088a547..082d1ac8a924 100644
--- a/include/console.h
+++ b/include/console.h
@@ -198,7 +198,9 @@ bool console_allow_color(void);
#ifndef CONFIG_CONSOLE_NONE
extern struct list_head console_list;
-#define for_each_console(console) list_for_each_entry(console, &console_list, list)
+#define for_each_console(console) \
+ scoped_var(struct console_device *console) \
+ list_for_each_entry(console, &console_list, list)
struct console_device *console_get_first_interactive(void);
@@ -210,7 +212,8 @@ static inline int barebox_set_loglevel(int loglevel)
return old_loglevel;
}
#else
-#define for_each_console(console) while (((void)console, 0))
+#define for_each_console(console) \
+ scoped_var(struct console_device *console) while (((void)console, 0))
static inline struct console_device *console_get_first_interactive(void)
{
diff --git a/lib/term.c b/lib/term.c
index 8b4de96c63a4..669d48fd4d8c 100644
--- a/lib/term.c
+++ b/lib/term.c
@@ -109,7 +109,6 @@ int term_getsize(int *screenwidth, int *screenheight)
{
int width = INT_MAX, height = INT_MAX;
bool found = false;
- struct console_device *cdev;
for_each_console(cdev) {
int w, h;
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 4/7] console: make console_puts and friends accept a console_device
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 2/7] stddef: implement scoped_var for use in iterators Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 3/7] console: have for_each_console declare the iterator internally Ahmad Fatoum
@ 2026-04-13 10:09 ` Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 5/7] console: implement console_putc in terms of console_putbin Ahmad Fatoum
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2026-04-13 10:09 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Ideally, stdout, stderr and stdin would be real consoles wit a custom
implementation that multiplexes onto all registered consoles that
are active for a given stream.
This will need some more carefulness though as not to increase size too
much for uninterested users.
We can already switch the API to a console_device-centric ones and reap
the benefits though by special casing the stdout/stderr/stdin types, so
do just that.
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
common/console.c | 49 ++++++++++++++++++++++------------
common/console_common.c | 14 +++++-----
common/console_simple.c | 4 +--
efi/loader/protocols/console.c | 2 +-
include/console.h | 21 +++++++++++----
include/stdio.h | 4 +--
pbl/console.c | 12 ++++-----
7 files changed, 66 insertions(+), 40 deletions(-)
diff --git a/common/console.c b/common/console.c
index d7013e72e358..014ce2916835 100644
--- a/common/console.c
+++ b/common/console.c
@@ -116,7 +116,7 @@ int console_set_active(struct console_device *cdev, unsigned flag)
puts_ll("]\n");
barebox_banner();
while (kfifo_getc(console_output_fifo, &ch) == 0)
- console_putc(CONSOLE_STDOUT, ch);
+ console_putc(CONSOLE_DEV_STDOUT, ch);
} else if (IS_ENABLED(CONFIG_BANNER) && cdev->puts &&
flag_new == CONSOLE_STDIOE) {
cdev->puts(cdev, version_string, strlen(version_string));
@@ -571,10 +571,18 @@ int tstc(void)
}
EXPORT_SYMBOL(tstc);
-int console_putc(unsigned int ch, char c)
+int console_putc(struct console_device *con, char c)
{
int init = initialized;
bool crlf = c == '\n';
+ unsigned int ch;
+
+ ch = console_dev_is_std(con);
+ if (!ch) {
+ if (crlf)
+ con->putc(con, '\r');
+ con->putc(con, c);
+ }
switch (init) {
case CONSOLE_UNINITIALIZED:
@@ -589,11 +597,8 @@ int console_putc(unsigned int ch, char c)
case CONSOLE_INIT_FULL:
for_each_console(cdev) {
- if (cdev->f_active & ch) {
- if (crlf)
- cdev->putc(cdev, '\r');
- cdev->putc(cdev, c);
- }
+ if (cdev->f_active & ch)
+ console_putc(cdev, c);
}
return 1 + crlf;
default:
@@ -605,16 +610,20 @@ int console_putc(unsigned int ch, char c)
}
EXPORT_SYMBOL(console_putc);
-int console_puts(unsigned int ch, const char *str)
+int console_puts(struct console_device *con, const char *str)
{
const char *s = str;
+ unsigned int ch;
int n = 0;
+ ch = console_dev_is_std(con);
+ if (!ch)
+ return con->puts(con, str, strlen(str));
+
if (initialized == CONSOLE_INIT_FULL) {
for_each_console(cdev) {
- if (cdev->f_active & ch) {
- n = cdev->puts(cdev, str, strlen(str));
- }
+ if (cdev->f_active & ch)
+ n = console_puts(cdev, str);
}
return n;
}
@@ -627,8 +636,17 @@ int console_puts(unsigned int ch, const char *str)
}
EXPORT_SYMBOL(console_puts);
-void console_putbin(unsigned int ch, const u8 *str, size_t len)
+void console_putbin(struct console_device *con, const u8 *str, size_t len)
{
+ unsigned int ch;
+
+ ch = console_dev_is_std(con);
+ if (!ch) {
+ for (size_t i = 0; i < len; i++)
+ con->putc(con, str[i]);
+ return;
+ }
+
switch (initialized) {
case CONSOLE_UNINITIALIZED:
console_init_early();
@@ -640,11 +658,8 @@ void console_putbin(unsigned int ch, const u8 *str, size_t len)
return;
case CONSOLE_INIT_FULL:
for_each_console(cdev) {
- if (!(cdev->f_active & ch))
- continue;
-
- for (size_t i = 0; i < len; i++)
- cdev->putc(cdev, str[i]);
+ if (cdev->f_active & ch)
+ console_putbin(cdev, str, len);
}
return;
default:
diff --git a/common/console_common.c b/common/console_common.c
index 1d98e4ec1bcc..86d9f523b1c5 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -73,7 +73,7 @@ void log_clean(unsigned int limit)
}
}
-static void print_colored_log_level(unsigned int ch, const int level)
+static void print_colored_log_level(struct console_device *con, const int level)
{
if (!console_allow_color())
return;
@@ -82,7 +82,7 @@ static void print_colored_log_level(unsigned int ch, const int level)
if (!colored_log_level[level])
return;
- console_puts(ch, colored_log_level[level]);
+ console_puts(con, colored_log_level[level]);
}
static void pr_puts(int level, const char *str)
@@ -116,8 +116,8 @@ static void pr_puts(int level, const char *str)
if (level > barebox_loglevel)
return;
- print_colored_log_level(CONSOLE_STDERR, level);
- console_puts(CONSOLE_STDERR, str);
+ print_colored_log_level(CONSOLE_DEV_STDERR, level);
+ console_puts(CONSOLE_DEV_STDERR, str);
}
int pr_print(int level, const char *fmt, ...)
@@ -237,7 +237,7 @@ int log_print(unsigned flags, unsigned levels)
if (!(flags & (BAREBOX_LOG_PRINT_RAW | BAREBOX_LOG_PRINT_TIME
| BAREBOX_LOG_DIFF_TIME)))
- print_colored_log_level(CONSOLE_STDOUT, log->level);
+ print_colored_log_level(CONSOLE_DEV_STDOUT, log->level);
if (flags & BAREBOX_LOG_PRINT_RAW)
printf("<%i>", log->level);
@@ -407,7 +407,7 @@ int dputs(int fd, const char *s)
if (fd == 1)
return puts(s);
else if (fd == 2)
- return console_puts(CONSOLE_STDERR, s);
+ return console_puts(CONSOLE_DEV_STDERR, s);
else
return write(fd, s, strlen(s));
}
@@ -418,7 +418,7 @@ int dputc(int fd, char c)
if (fd == 1)
putchar(c);
else if (fd == 2)
- return console_putc(CONSOLE_STDERR, c);
+ return console_putc(CONSOLE_DEV_STDERR, c);
else
return write(fd, &c, 1);
diff --git a/common/console_simple.c b/common/console_simple.c
index dfc180e70f98..563fc542be58 100644
--- a/common/console_simple.c
+++ b/common/console_simple.c
@@ -11,7 +11,7 @@ LIST_HEAD(console_list);
EXPORT_SYMBOL(console_list);
static struct console_device *console;
-int console_puts(unsigned int ch, const char *str)
+int console_puts(struct console_device *con, const char *str)
{
const char *s = str;
int i = 0;
@@ -25,7 +25,7 @@ int console_puts(unsigned int ch, const char *str)
}
EXPORT_SYMBOL(console_puts);
-int console_putc(unsigned int ch, char c)
+int console_putc(struct console_device *con, char c)
{
bool crlf = c == '\n';
if (!console) {
diff --git a/efi/loader/protocols/console.c b/efi/loader/protocols/console.c
index 4545d94c6fae..a7395a24ad18 100644
--- a/efi/loader/protocols/console.c
+++ b/efi/loader/protocols/console.c
@@ -124,7 +124,7 @@ static efi_status_t EFIAPI efi_cout_output_string(
end = utf16_to_utf8(utf8, p, is_high_surrogate ? 2 : 1);
/* console_puts turns \n into \r\n, which we want to avoid */
- console_putbin(CONSOLE_STDOUT, utf8, end - utf8);
+ console_putbin(CONSOLE_DEV_STDOUT, utf8, end - utf8);
switch (*p) {
case '\b': /* U+0008, backspace */
diff --git a/include/console.h b/include/console.h
index 082d1ac8a924..5a4dbcdf1327 100644
--- a/include/console.h
+++ b/include/console.h
@@ -21,6 +21,10 @@
#define CONSOLE_STDIOE (CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR)
+#define CONSOLE_DEV_STDIN ((void *)CONSOLE_STDIN)
+#define CONSOLE_DEV_STDOUT ((void *)CONSOLE_STDOUT)
+#define CONSOLE_DEV_STDERR ((void *)CONSOLE_STDERR)
+
enum console_mode {
CONSOLE_MODE_NORMAL,
CONSOLE_MODE_RS485,
@@ -88,6 +92,13 @@ console_is_serdev_node(struct console_device *cdev)
return NULL;
}
+static inline unsigned int console_dev_is_std(struct console_device *con)
+{
+ if ((uintptr_t)con > CONSOLE_STDERR)
+ return 0;
+ return (uintptr_t)con & CONSOLE_STDIOE;
+}
+
int console_register(struct console_device *cdev);
int console_unregister(struct console_device *cdev);
@@ -232,9 +243,9 @@ int arch_ctrlc(void);
#ifndef CONFIG_CONSOLE_NONE
/* stdout */
-int console_putc(unsigned int ch, const char c);
-int console_puts(unsigned int ch, const char *s);
-void console_putbin(unsigned int ch, const u8 *str, size_t len);
+int console_putc(struct console_device *con, const char c);
+int console_puts(struct console_device *con, const char *s);
+void console_putbin(struct console_device *con, const u8 *str, size_t len);
void console_flush(void);
int ctrlc(void);
@@ -243,8 +254,8 @@ void ctrlc_handled(void);
void console_ctrlc_allow(void);
void console_ctrlc_forbid(void);
#else
-static inline int console_puts(unsigned int ch, const char *str) { return 0; }
-static inline int console_putc(unsigned int ch, char c) { return 0;}
+static inline int console_puts(struct console_device *con, const char *str) { return 0; }
+static inline int console_putc(struct console_device *con, char c) { return 0; }
static inline void console_flush(void) {}
/* test if ctrl-c was pressed */
diff --git a/include/stdio.h b/include/stdio.h
index 4c0dff0c0084..f5b23140adde 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -22,8 +22,8 @@ int readline(const char *prompt, char *buf, int len);
#if (IN_PROPER && !defined(CONFIG_CONSOLE_NONE)) || \
(IN_PBL && defined(CONFIG_PBL_CONSOLE))
int vprintf(const char *fmt, va_list args);
-static inline int puts(const char *s) { return console_puts(CONSOLE_STDOUT, s); }
-static inline void putchar(char c) { console_putc(CONSOLE_STDOUT, c); }
+static inline int puts(const char *s) { return console_puts(CONSOLE_DEV_STDOUT, s); }
+static inline void putchar(char c) { console_putc(CONSOLE_DEV_STDOUT, c); }
#else
static inline int puts(const char *s) { return 0; }
static inline void putchar(char c) {}
diff --git a/pbl/console.c b/pbl/console.c
index 1274552b2088..54da10a8e9ae 100644
--- a/pbl/console.c
+++ b/pbl/console.c
@@ -32,7 +32,7 @@ static void __putc(void *ctx, int c)
putc(ctx, c);
}
-int console_putc(unsigned int ch, char c)
+int console_putc(struct console_device *con, char c)
{
if (putc_offset)
__putc(putc_ctx, c);
@@ -42,17 +42,17 @@ int console_putc(unsigned int ch, char c)
return 1;
}
-int console_puts(unsigned int ch, const char *str)
+int console_puts(struct console_device *con, const char *str)
{
int n = 0;
while (*str) {
if (*str == '\n') {
- console_putc(ch, '\r');
+ console_putc(con, '\r');
n++;
}
- console_putc(ch, *str);
+ console_putc(con, *str);
str++;
n++;
}
@@ -72,7 +72,7 @@ int vprintf(const char *fmt, va_list args)
i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
/* Print the string */
- console_puts(CONSOLE_STDOUT, printbuffer);
+ console_puts(CONSOLE_DEV_STDOUT, printbuffer);
return i;
}
@@ -99,7 +99,7 @@ int pr_print(int level, const char *fmt, ...)
i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
va_end(args);
- console_puts(CONSOLE_STDERR, printbuffer);
+ console_puts(CONSOLE_DEV_STDERR, printbuffer);
return i;
}
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 5/7] console: implement console_putc in terms of console_putbin
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
` (2 preceding siblings ...)
2026-04-13 10:09 ` [PATCH 4/7] console: make console_puts and friends accept a console_device Ahmad Fatoum
@ 2026-04-13 10:09 ` Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 6/7] console: implement console_printf Ahmad Fatoum
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2026-04-13 10:09 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
console_putc() and console_putbin() both have logic to handle different
stages of console initialization.
Implement the former in terms of the latter to remove the duplication.
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
common/console.c | 36 +++++-------------------------------
1 file changed, 5 insertions(+), 31 deletions(-)
diff --git a/common/console.c b/common/console.c
index 014ce2916835..0ce89390864b 100644
--- a/common/console.c
+++ b/common/console.c
@@ -573,40 +573,14 @@ EXPORT_SYMBOL(tstc);
int console_putc(struct console_device *con, char c)
{
- int init = initialized;
bool crlf = c == '\n';
- unsigned int ch;
- ch = console_dev_is_std(con);
- if (!ch) {
- if (crlf)
- con->putc(con, '\r');
- con->putc(con, c);
- }
+ if (crlf)
+ console_putbin(con, "\r\n", 2);
+ else
+ console_putbin(con, &c, 1);
- switch (init) {
- case CONSOLE_UNINITIALIZED:
- console_init_early();
- fallthrough;
- case CONSOLE_INITIALIZED_BUFFER:
- kfifo_putc(console_output_fifo, c);
- if (crlf)
- putc_ll('\r');
- putc_ll(c);
- return 1 + crlf;
-
- case CONSOLE_INIT_FULL:
- for_each_console(cdev) {
- if (cdev->f_active & ch)
- console_putc(cdev, c);
- }
- return 1 + crlf;
- default:
- /* If we have problems inititalizing our data
- * get them early
- */
- hang();
- }
+ return 1 + crlf;
}
EXPORT_SYMBOL(console_putc);
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 6/7] console: implement console_printf
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
` (3 preceding siblings ...)
2026-04-13 10:09 ` [PATCH 5/7] console: implement console_putc in terms of console_putbin Ahmad Fatoum
@ 2026-04-13 10:09 ` Ahmad Fatoum
2026-04-13 10:09 ` [PATCH 7/7] commands: dmesg: give log_print a console_device parameter Ahmad Fatoum
2026-04-13 12:28 ` [PATCH 1/7] console: return characters written from console_putc Sascha Hauer
6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2026-04-13 10:09 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
printf formats to a buffer and then prints it out with puts().
Allow printing to arbitrary consoles while reusing this logic by adding
a new console_printf().
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
common/console_common.c | 29 ++++++++++++++++++++++++-----
include/console.h | 3 +++
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/common/console_common.c b/common/console_common.c
index 86d9f523b1c5..310534affa58 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -266,7 +266,7 @@ int log_print(unsigned flags, unsigned levels)
return 0;
}
-int printf(const char *fmt, ...)
+int console_printf(struct console_device *con, const char *fmt, ...)
{
va_list args;
int i;
@@ -282,13 +282,13 @@ int printf(const char *fmt, ...)
va_end(args);
/* Print the string */
- puts(printbuffer);
+ console_puts(con, printbuffer);
return i;
}
-EXPORT_SYMBOL(printf);
+EXPORT_SYMBOL(console_printf);
-int vprintf(const char *fmt, va_list args)
+int console_vprintf(struct console_device *con, const char *fmt, va_list args)
{
int i;
char printbuffer[CFG_PBSIZE];
@@ -300,10 +300,29 @@ int vprintf(const char *fmt, va_list args)
i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
/* Print the string */
- puts(printbuffer);
+ console_puts(con, printbuffer);
return i;
}
+EXPORT_SYMBOL(console_vprintf);
+
+int printf(const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = console_vprintf(CONSOLE_DEV_STDOUT, fmt, args);
+ va_end(args);
+
+ return i;
+}
+EXPORT_SYMBOL(printf);
+
+int vprintf(const char *fmt, va_list args)
+{
+ return console_vprintf(CONSOLE_DEV_STDOUT, fmt, args);
+}
EXPORT_SYMBOL(vprintf);
struct console_device *console_get_by_dev(struct device *dev)
diff --git a/include/console.h b/include/console.h
index 5a4dbcdf1327..ed5b501b65a4 100644
--- a/include/console.h
+++ b/include/console.h
@@ -248,6 +248,9 @@ int console_puts(struct console_device *con, const char *s);
void console_putbin(struct console_device *con, const u8 *str, size_t len);
void console_flush(void);
+int console_printf(struct console_device *con, const char *fmt, ...) __printf(2, 3);
+int console_vprintf(struct console_device *con, const char *fmt, va_list args);
+
int ctrlc(void);
int ctrlc_non_interruptible(void);
void ctrlc_handled(void);
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 7/7] commands: dmesg: give log_print a console_device parameter
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
` (4 preceding siblings ...)
2026-04-13 10:09 ` [PATCH 6/7] console: implement console_printf Ahmad Fatoum
@ 2026-04-13 10:09 ` Ahmad Fatoum
2026-04-13 12:28 ` [PATCH 1/7] console: return characters written from console_putc Sascha Hauer
6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2026-04-13 10:09 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
log_print currently prints out unconditionally to stdout and thus has no
support for printing to a single specific console, e.g. the framebuffer
console.
Make use of the new console_printf() to address this.
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
commands/dmesg.c | 2 +-
common/console_common.c | 17 +++++++++--------
include/linux/printk.h | 3 ++-
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/commands/dmesg.c b/commands/dmesg.c
index 0313c8cdea74..06796287aaec 100644
--- a/commands/dmesg.c
+++ b/commands/dmesg.c
@@ -158,7 +158,7 @@ static int do_dmesg(int argc, char *argv[])
return 0;
}
- ret = log_print(flags, levels);
+ ret = log_print(CONSOLE_DEV_STDOUT, flags, levels);
if (ret)
return 1;
diff --git a/common/console_common.c b/common/console_common.c
index 310534affa58..de0a213f833c 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -215,13 +215,14 @@ int log_writefile(const char *filepath)
/**
* log_print - print the log buffer
*
+ * @con: Console device to print to
* @flags: Flags selecting output formatting
* @levels: bitmask of loglevels to print, 0 for all
*
* This function prints the messages of the selected levels; optionally with
* additional information and formatting.
*/
-int log_print(unsigned flags, unsigned levels)
+int log_print(struct console_device *con, unsigned flags, unsigned levels)
{
struct log_entry *log;
unsigned long last = 0;
@@ -237,30 +238,30 @@ int log_print(unsigned flags, unsigned levels)
if (!(flags & (BAREBOX_LOG_PRINT_RAW | BAREBOX_LOG_PRINT_TIME
| BAREBOX_LOG_DIFF_TIME)))
- print_colored_log_level(CONSOLE_DEV_STDOUT, log->level);
+ print_colored_log_level(con, log->level);
if (flags & BAREBOX_LOG_PRINT_RAW)
- printf("<%i>", log->level);
+ console_printf(con, "<%i>", log->level);
/* convert ns to us */
do_div(time_ns, 1000);
time = time_ns;
if (flags & (BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME))
- printf("[");
+ console_printf(con, "[");
if (flags & BAREBOX_LOG_PRINT_TIME)
- printf("%10luus", time);
+ console_printf(con, "%10luus", time);
if (flags & BAREBOX_LOG_DIFF_TIME) {
- printf(" < %10luus", time - last);
+ console_printf(con, " < %10luus", time - last);
last = time;
}
if (flags & (BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME))
- printf("] ");
+ console_printf(con, "] ");
- printf("%s", log->msg);
+ console_printf(con, "%s", log->msg);
}
return 0;
diff --git a/include/linux/printk.h b/include/linux/printk.h
index deaaa44b31a7..4d6df821e1f1 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -192,7 +192,8 @@ extern void log_clean(unsigned int limit);
#define BAREBOX_LOG_PRINT_TIME BIT(0)
int log_writefile(const char *filepath);
-int log_print(unsigned flags, unsigned levels);
+struct console_device;
+int log_print(struct console_device *console, unsigned flags, unsigned levels);
struct va_format {
const char *fmt;
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/7] console: return characters written from console_putc
2026-04-13 10:09 [PATCH 1/7] console: return characters written from console_putc Ahmad Fatoum
` (5 preceding siblings ...)
2026-04-13 10:09 ` [PATCH 7/7] commands: dmesg: give log_print a console_device parameter Ahmad Fatoum
@ 2026-04-13 12:28 ` Sascha Hauer
6 siblings, 0 replies; 8+ messages in thread
From: Sascha Hauer @ 2026-04-13 12:28 UTC (permalink / raw)
To: barebox, Ahmad Fatoum
On Mon, 13 Apr 2026 12:09:36 +0200, Ahmad Fatoum wrote:
> console_putc() prints two characters instead of one when it does
> LF -> CRLF conversion.
>
> As console_putc already has to do the CRLF check, have it return the
> number of printed characters as well to simplify its users.
>
>
> [...]
Applied, thanks!
[1/7] console: return characters written from console_putc
https://git.pengutronix.de/cgit/barebox/commit/?id=1f2f5516f3ec (link may not be stable)
[2/7] stddef: implement scoped_var for use in iterators
https://git.pengutronix.de/cgit/barebox/commit/?id=59b568e3f41d (link may not be stable)
[3/7] console: have for_each_console declare the iterator internally
https://git.pengutronix.de/cgit/barebox/commit/?id=2cd7ffac2800 (link may not be stable)
[4/7] console: make console_puts and friends accept a console_device
https://git.pengutronix.de/cgit/barebox/commit/?id=1c0c83499823 (link may not be stable)
[5/7] console: implement console_putc in terms of console_putbin
https://git.pengutronix.de/cgit/barebox/commit/?id=7d1261885109 (link may not be stable)
[6/7] console: implement console_printf
https://git.pengutronix.de/cgit/barebox/commit/?id=ec7d76d5dee5 (link may not be stable)
[7/7] commands: dmesg: give log_print a console_device parameter
https://git.pengutronix.de/cgit/barebox/commit/?id=ae1bbd2ab824 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 8+ messages in thread