From 8af1da40669609707303eecdb857f48a5ba5792d Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Tue, 29 May 2018 21:20:01 +0200 Subject: [PATCH] powerpc/prom: Fix %u/%llx usage since prom_printf() change 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 Reported-by: Stephen Rothwell Signed-off-by: Mathieu Malaterre Tested-by: Michael Ellerman Signed-off-by: Michael Ellerman --- arch/powerpc/kernel/prom_init.c | 73 +++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 425992e..5425dd3 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -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; } } -- 2.7.4