powerpc/prom: Fix %u/%llx usage since prom_printf() change
authorMathieu Malaterre <malat@debian.org>
Tue, 29 May 2018 19:20:01 +0000 (21:20 +0200)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 1 Jun 2018 15:48:11 +0000 (01:48 +1000)
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 prints 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 <mpe@ellerman.id.au>
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Mathieu Malaterre <malat@debian.org>
Tested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kernel/prom_init.c

index 425992e..5425dd3 100644 (file)
@@ -301,6 +301,10 @@ 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 +345,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 +364,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 +376,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;
                }
        }