From 7840e5e95c1a8622425f11454600a49b6c718886 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 8 Jun 2005 15:12:00 +1000 Subject: [PATCH] [PATCH] ppc64: print negative numbers correctly in boot wrapper if num has a value of -1, accessing the digits[] array will fail and the format string will be printed in funny way, or not at all. This happens if one prints negative numbers. Just change the code to match lib/vsprintf.c asm/div64.h cant be used because u64 maps to u32 for this build. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/ppc64/boot/prom.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/arch/ppc64/boot/prom.c b/arch/ppc64/boot/prom.c index 7b607d1862cb..d5218b15824e 100644 --- a/arch/ppc64/boot/prom.c +++ b/arch/ppc64/boot/prom.c @@ -11,6 +11,23 @@ #include #include +extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor); + +/* The unnecessary pointer compare is there + * to check for type safety (n must be 64bit) + */ +# define do_div(n,base) ({ \ + __u32 __base = (base); \ + __u32 __rem; \ + (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ + if (((n) >> 32) == 0) { \ + __rem = (__u32)(n) % __base; \ + (n) = (__u32)(n) / __base; \ + } else \ + __rem = __div64_32(&(n), __base); \ + __rem; \ + }) + int (*prom)(void *); void *chosen_handle; @@ -352,7 +369,7 @@ static int skip_atoi(const char **s) #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ -static char * number(char * str, long num, int base, int size, int precision, int type) +static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; @@ -367,9 +384,9 @@ static char * number(char * str, long num, int base, int size, int precision, in c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { - if (num < 0) { + if ((signed long long)num < 0) { sign = '-'; - num = -num; + num = - (signed long long)num; size--; } else if (type & PLUS) { sign = '+'; @@ -389,8 +406,7 @@ static char * number(char * str, long num, int base, int size, int precision, in if (num == 0) tmp[i++]='0'; else while (num != 0) { - tmp[i++] = digits[num % base]; - num /= base; + tmp[i++] = digits[do_div(num, base)]; } if (i > precision) precision = i; @@ -426,7 +442,7 @@ int sprintf(char * buf, const char *fmt, ...); int vsprintf(char *buf, const char *fmt, va_list args) { int len; - unsigned long num; + unsigned long long num; int i, base; char * str; const char *s; -- 2.30.2