The formatting with %pa / %pap behaves like %x, which results in an incorrect value being output. To improve this, a new fine-tuning Kconfig SPL_USE_TINY_PRINTF_POINTER_SUPPORT for pointer formatting has been added. If it is enabled, the output of %pa / %pap should be correct, and if it is disabled, the pointer formatting is completely unsupported. In addition to indicate unsupported formatting, '?' will be output. This allows enabling pointer formatting only when needed. For SPL_NET it is selected by default. Then it also supports the formatting with %pm, %pM and %pI4.
In summery this level of %p support for tiny printf is possible now: 1) The standard tiny printf won't have support for pointer formatting. So it doesn't print misleading values for %pa, instead '?' will be output: %p => ? %pa => ?a %pap => ?ap 2) If SPL_USE_TINY_PRINTF_POINTER_SUPPORT is enabled or DEBUG is defined tiny printf supports formatting %p and %pa / %pap. 3) If SPL_NET is enabled the support of pointers is extended for %pm, %pM and %pI4. Signed-off-by: Christoph Niedermaier <cniederma...@dh-electronics.com> --- Cc: Tom Rini <tr...@konsulko.com> Cc: Simon Glass <s...@chromium.org> Cc: Michael Walle <mwa...@kernel.org> Cc: Quentin Schulz <quentin.sch...@cherry.de> Cc: Marek Vasut <ma...@denx.de> Cc: Benedikt Spranger <b.spran...@linutronix.de> Cc: Jerome Forissier <jerome.foriss...@linaro.org> Cc: John Ogness <john.ogn...@linutronix.de> Cc: Ilias Apalodimas <ilias.apalodi...@linaro.org> --- V2: - Rebase on current master - Extend commit message - Restrict use to SPL - Rename Kconfig to SPL_USE_TINY_PRINTF_POINTER_SUPPORT - Replace _DEBUG with defined(DEBUG) - Output '?' if %pm, %pM and %pI4 isn't available - Add break on case '%' V3: - Add missing output '?' for the default case V4: - Remove NET_LWIP support from tiny printf because SPL doesn't support lwIP --- common/spl/Kconfig | 1 + lib/Kconfig | 8 ++++++++ lib/tiny-printf.c | 48 +++++++++++++++++++++++----------------------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 0bc96d0a781..49dd0c1cb0e 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -1122,6 +1122,7 @@ config SPL_DM_SPI_FLASH config SPL_NET bool "Support networking" depends on !NET_LWIP + select SPL_USE_TINY_PRINTF_POINTER_SUPPORT if SPL_USE_TINY_PRINTF help Enable support for network devices (such as Ethernet) in SPL. This permits SPL to load U-Boot over a network link rather than diff --git a/lib/Kconfig b/lib/Kconfig index b2aecd8a49e..cdf8f7ee0e8 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -253,6 +253,14 @@ config VPL_USE_TINY_PRINTF The supported format specifiers are %c, %s, %u/%d and %x. +config SPL_USE_TINY_PRINTF_POINTER_SUPPORT + bool "Extend tiny printf with the pointer formatting %p" + depends on SPL_USE_TINY_PRINTF + help + This option enables the formatting of pointers %p. It supports + %p and %pa / %pap. If this option is selected by SPL_NET + it also supports the formatting with %pm, %pM and %pI4. + config PANIC_HANG bool "Do not reset the system on fatal error" help diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 2a7a4d286c0..411ae6189f2 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -141,7 +141,7 @@ static void ip4_addr_string(struct printf_info *info, u8 *addr) string(info, ip4_addr); } -#endif +#endif /* CONFIG_SPL_NET */ /* * Show a '%p' thing. A kernel extension is that the '%p' is followed @@ -157,18 +157,14 @@ static void ip4_addr_string(struct printf_info *info, u8 *addr) * decimal). */ -static void __maybe_unused pointer(struct printf_info *info, const char *fmt, - void *ptr) +#if defined(CONFIG_SPL_USE_TINY_PRINTF_POINTER_SUPPORT) || defined(DEBUG) +static void pointer(struct printf_info *info, const char *fmt, void *ptr) { -#ifdef DEBUG unsigned long num = (uintptr_t)ptr; unsigned long div; -#endif switch (*fmt) { -#ifdef DEBUG case 'a': - switch (fmt[1]) { case 'p': default: @@ -176,7 +172,6 @@ static void __maybe_unused pointer(struct printf_info *info, const char *fmt, break; } break; -#endif #ifdef CONFIG_SPL_NET case 'm': return mac_address_string(info, ptr, false); @@ -185,16 +180,22 @@ static void __maybe_unused pointer(struct printf_info *info, const char *fmt, case 'I': if (fmt[1] == '4') return ip4_addr_string(info, ptr); +#else + case 'm': + case 'M': + case 'I': + out(info, '?'); + return; #endif default: break; } -#ifdef DEBUG + div = 1UL << (sizeof(long) * 8 - 4); for (; div; div /= 0x10) div_out(info, &num, div); -#endif } +#endif static int _vprintf(struct printf_info *info, const char *fmt, va_list va) { @@ -269,21 +270,18 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) div_out(info, &num, div); } break; +#if defined(CONFIG_SPL_USE_TINY_PRINTF_POINTER_SUPPORT) || defined(DEBUG) case 'p': - if (CONFIG_IS_ENABLED(NET) || - CONFIG_IS_ENABLED(NET_LWIP) || _DEBUG) { - pointer(info, fmt, va_arg(va, void *)); - /* - * Skip this because it pulls in _ctype which is - * 256 bytes, and we don't generally implement - * pointer anyway - */ - while (isalnum(fmt[0])) - fmt++; - break; - } - islong = true; - fallthrough; + pointer(info, fmt, va_arg(va, void *)); + /* + * Skip this because it pulls in _ctype which is + * 256 bytes, and we don't generally implement + * pointer anyway + */ + while (isalnum(fmt[0])) + fmt++; + break; +#endif case 'x': case 'X': if (islong) { @@ -310,7 +308,9 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) break; case '%': out(info, '%'); + break; default: + out(info, '?'); break; } -- 2.30.2