]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
tiny-printf: Handle formatting of %p with an extra Kconfig
authorChristoph Niedermaier <cniedermaier@dh-electronics.com>
Thu, 8 May 2025 11:57:25 +0000 (13:57 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 22 May 2025 16:57:12 +0000 (10:57 -0600)
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 <cniedermaier@dh-electronics.com>
common/spl/Kconfig
lib/Kconfig
lib/tiny-printf.c

index aa3a85eea54d851b9ab8cf54b019c0001c58d1b6..a84a0f8392415b91133da1e089ba75272843020d 100644 (file)
@@ -1123,6 +1123,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
index b2aecd8a49e8107cbb0346a73ade6a0383472f85..cdf8f7ee0e8e5e5141c00c5b4de8fc5b0d32a0f2 100644 (file)
@@ -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
index 2a7a4d286c0b3aee3f6a6a35f47b8109b376be4b..411ae6189f29bcc3d81c0ae2f24623d2603878f6 100644 (file)
@@ -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;
                        }