In commit eae5f709a4d7 ("powerpc: Add __printf verification to
prom_printf") __printf attribute was added to prom_printf(), which
means GCC started warning about type/format mismatches. As part of that
commit we changed some "%lx" formats to "%llx" where the type is
actually unsigned long long.

Unfortunately prom_printf() doesn't know how to print "%llx", it just
prints a literal "lx", eg:

  reserved memory map:
    lx - lx
    lx - lx

prom_printf() also doesn't know how to print "%u" (only "%lu"), it just
print a literal "u", eg:

  Max number of cores passed to firmware: u (NR_CPUS = 2048)

instead of:

  Max number of cores passed to firmware: 2048 (NR_CPUS = 2048)

This commit adds support for the missing formatters.

Fixes: eae5f709a4d7 ("powerpc: Add __printf verification to prom_printf")
Reported-by: Michael Ellerman <m...@ellerman.id.au>
Reported-by: Stephen Rothwell <s...@canb.auug.org.au>
Signed-off-by: Mathieu Malaterre <ma...@debian.org>
---
I've reviewed all formatters added in eae5f709a4d7 and only %u and %llx were
actually missing (eg. llu or lld are not used)

 arch/powerpc/kernel/prom_init.c | 72 +++++++++++++++++++++++++++--------------
 1 file changed, 48 insertions(+), 24 deletions(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 4d62f561f272..2c04516fe274 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -301,6 +301,9 @@ static void __init prom_print(const char *msg)
 }
 
 
+/* both prom_print_hex & prom_print_dec takes an unsigned long as input so that
+ * we do not need __udivdi3 or __umoddi3 on 32bits
+ */
 static void __init prom_print_hex(unsigned long val)
 {
        int i, nibbles = sizeof(val)*2;
@@ -341,6 +344,7 @@ static void __init prom_printf(const char *format, ...)
        va_list args;
        unsigned long v;
        long vs;
+       int n = 0;
 
        va_start(args, format);
        for (p = format; *p != 0; p = q) {
@@ -359,6 +363,10 @@ static void __init prom_printf(const char *format, ...)
                ++q;
                if (*q == 0)
                        break;
+               while (*q == 'l') {
+                       ++q;
+                       ++n;
+               }
                switch (*q) {
                case 's':
                        ++q;
@@ -367,39 +375,55 @@ static void __init prom_printf(const char *format, ...)
                        break;
                case 'x':
                        ++q;
-                       v = va_arg(args, unsigned long);
+                       switch (n) {
+                       case 0:
+                               v = va_arg(args, unsigned int);
+                               break;
+                       case 1:
+                               v = va_arg(args, unsigned long);
+                               break;
+                       case 2:
+                       default:
+                               v = va_arg(args, unsigned long long);
+                               break;
+                       }
                        prom_print_hex(v);
                        break;
-               case 'd':
+               case 'u':
                        ++q;
-                       vs = va_arg(args, int);
-                       if (vs < 0) {
-                               prom_print("-");
-                               vs = -vs;
+                       switch (n) {
+                       case 0:
+                               v = va_arg(args, unsigned int);
+                               break;
+                       case 1:
+                               v = va_arg(args, unsigned long);
+                               break;
+                       case 2:
+                       default:
+                               v = va_arg(args, unsigned long long);
+                               break;
                        }
-                       prom_print_dec(vs);
+                       prom_print_dec(v);
                        break;
-               case 'l':
+               case 'd':
                        ++q;
-                       if (*q == 0)
+                       switch (n) {
+                       case 0:
+                               vs = va_arg(args, int);
                                break;
-                       else if (*q == 'x') {
-                               ++q;
-                               v = va_arg(args, unsigned long);
-                               prom_print_hex(v);
-                       } else if (*q == 'u') { /* '%lu' */
-                               ++q;
-                               v = va_arg(args, unsigned long);
-                               prom_print_dec(v);
-                       } else if (*q == 'd') { /* %ld */
-                               ++q;
+                       case 1:
                                vs = va_arg(args, long);
-                               if (vs < 0) {
-                                       prom_print("-");
-                                       vs = -vs;
-                               }
-                               prom_print_dec(vs);
+                               break;
+                       case 2:
+                       default:
+                               vs = va_arg(args, long long);
+                               break;
+                       }
+                       if (vs < 0) {
+                               prom_print("-");
+                               vs = -vs;
                        }
+                       prom_print_dec(vs);
                        break;
                }
        }
-- 
2.11.0

Reply via email to