[U-Boot] [PATCH 1/4 v2] common/console.c: Drop sandbox special-case console code

As done in commit da229e4e [sandbox: Drop special-case sandbox console code], this patch drops the sandbox special-case code in vprintf() that was missed by Simon at that time.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org --- v2: - new patch
common/console.c | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/common/console.c b/common/console.c index ace206c..6fd7a10 100644 --- a/common/console.c +++ b/common/console.c @@ -559,11 +559,6 @@ int vprintf(const char *fmt, va_list args) uint i; char printbuffer[CONFIG_SYS_PBSIZE];
-#if defined(CONFIG_PRE_CONSOLE_BUFFER) && !defined(CONFIG_SANDBOX) - if (!gd->have_console) - return 0; -#endif - /* For this to work, printbuffer must be larger than * anything we ever want to print. */

Change some comments to match the U-Boot coding style rules.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org --- v2: - new patch
common/console.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/common/console.c b/common/console.c index 6fd7a10..cf86b76 100644 --- a/common/console.c +++ b/common/console.c @@ -543,7 +543,8 @@ int printf(const char *fmt, ...)
va_start(args, fmt);
- /* For this to work, printbuffer must be larger than + /* + * For this to work, printbuffer must be larger than * anything we ever want to print. */ i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); @@ -559,7 +560,8 @@ int vprintf(const char *fmt, va_list args) uint i; char printbuffer[CONFIG_SYS_PBSIZE];
- /* For this to work, printbuffer must be larger than + /* + * For this to work, printbuffer must be larger than * anything we ever want to print. */ i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);

On 16 November 2015 at 07:26, Stefan Roese sr@denx.de wrote:
Change some comments to match the U-Boot coding style rules.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org
v2:
- new patch
common/console.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

On Mon, Nov 16, 2015 at 03:26:32PM +0100, Stefan Roese wrote:
Change some comments to match the U-Boot coding style rules.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!

This patch adds a small printf() version that supports all basic formats. Its intented to be used in U-Boot SPL versions on platforms with very limited internal RAM sizes.
To enable it, just define CONFIG_USE_TINY_PRINTF in your defconfig. This will result in the SPL using this tiny function and the main U-Boot still using the full-blown printf() function.
This code was copied from: http://www.sparetimelabs.com/printfrevisited With mostly only coding style related changes so that its checkpatch clean.
The size reduction is about 2.5KiB. Here a comparison for the db-mv784mp-gp (Marvell AXP) SPL:
Without this patch: 58963 18536 1928 79427 13643 ./spl/u-boot-spl
With this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
Note: To make it possible to compile tiny-printf.c instead of vsprintf.c when CONFIG_USE_TINY_PRINTF is defined, the functions printf() and vprintf() are moved from common/console.c into vsprintf.c in this patch.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net --- v2: - Patch split-up into multiple patches - Added comment about supported formats in Kconfig
common/console.c | 36 --------------- lib/Kconfig | 10 +++++ lib/Makefile | 7 ++- lib/tiny-printf.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/vsprintf.c | 36 +++++++++++++++ 5 files changed, 182 insertions(+), 37 deletions(-) create mode 100644 lib/tiny-printf.c
diff --git a/common/console.c b/common/console.c index cf86b76..2bfd59f 100644 --- a/common/console.c +++ b/common/console.c @@ -535,42 +535,6 @@ void puts(const char *s) } }
-int printf(const char *fmt, ...) -{ - va_list args; - uint i; - char printbuffer[CONFIG_SYS_PBSIZE]; - - va_start(args, fmt); - - /* - * For this to work, printbuffer must be larger than - * anything we ever want to print. - */ - i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); - va_end(args); - - /* Print the string */ - puts(printbuffer); - return i; -} - -int vprintf(const char *fmt, va_list args) -{ - uint i; - char printbuffer[CONFIG_SYS_PBSIZE]; - - /* - * For this to work, printbuffer must be larger than - * anything we ever want to print. - */ - i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); - - /* Print the string */ - puts(printbuffer); - return i; -} - /* test if ctrl-c was pressed */ static int ctrlc_disabled = 0; /* see disable_ctrl() */ static int ctrlc_was_pressed = 0; diff --git a/lib/Kconfig b/lib/Kconfig index 30e84ed..9d580e4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -36,6 +36,16 @@ config SYS_VSNPRINTF Thumb-2, about 420 bytes). Enable this option for safety when using sprintf() with data you do not control.
+config USE_TINY_PRINTF + bool "Enable tiny printf() version" + help + This option enables a tiny, stripped down printf version. + This should only be used in space limited environments, + like SPL versions with hard memory limits. This version + reduces the code size by about 2.5KiB on armv7. + + The supported format specifiers are %c, %s, %u/%d and %x. + config REGEX bool "Enable regular expression support" default y if NET diff --git a/lib/Makefile b/lib/Makefile index 3eecefa..54b6555 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -79,7 +79,12 @@ obj-y += string.o obj-y += time.o obj-$(CONFIG_TRACE) += trace.o obj-$(CONFIG_LIB_UUID) += uuid.o -obj-y += vsprintf.o obj-$(CONFIG_LIB_RAND) += rand.o
+ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_USE_TINY_PRINTF),yy) +obj-y += tiny-printf.o +else +obj-y += vsprintf.o +endif + subdir-ccflags-$(CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED) += -O2 diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c new file mode 100644 index 0000000..d743a36 --- /dev/null +++ b/lib/tiny-printf.c @@ -0,0 +1,130 @@ +/* + * Tiny printf version for SPL + * + * Copied from: + * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php + * + * Copyright (C) 2004,2008 Kustaa Nyholm + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include <common.h> +#include <stdarg.h> +#include <serial.h> + +static char *bf; +static char buf[12]; +static unsigned int num; +static char uc; +static char zs; + +static void out(char c) +{ + *bf++ = c; +} + +static void out_dgt(char dgt) +{ + out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10)); + zs = 1; +} + +static void div_out(unsigned int div) +{ + unsigned char dgt = 0; + + num &= 0xffff; /* just for testing the code with 32 bit ints */ + while (num >= div) { + num -= div; + dgt++; + } + + if (zs || dgt > 0) + out_dgt(dgt); +} + +int printf(const char *fmt, ...) +{ + va_list va; + char ch; + char *p; + + va_start(va, fmt); + + while ((ch = *(fmt++))) { + if (ch != '%') { + putc(ch); + } else { + char lz = 0; + char w = 0; + + ch = *(fmt++); + if (ch == '0') { + ch = *(fmt++); + lz = 1; + } + + if (ch >= '0' && ch <= '9') { + w = 0; + while (ch >= '0' && ch <= '9') { + w = (((w << 2) + w) << 1) + ch - '0'; + ch = *fmt++; + } + } + bf = buf; + p = bf; + zs = 0; + + switch (ch) { + case 0: + goto abort; + case 'u': + case 'd': + num = va_arg(va, unsigned int); + if (ch == 'd' && (int)num < 0) { + num = -(int)num; + out('-'); + } + div_out(10000); + div_out(1000); + div_out(100); + div_out(10); + out_dgt(num); + break; + case 'x': + case 'X': + uc = ch == 'X'; + num = va_arg(va, unsigned int); + div_out(0x1000); + div_out(0x100); + div_out(0x10); + out_dgt(num); + break; + case 'c': + out((char)(va_arg(va, int))); + break; + case 's': + p = va_arg(va, char*); + break; + case '%': + out('%'); + default: + break; + } + + *bf = 0; + bf = p; + while (*bf++ && w > 0) + w--; + while (w-- > 0) + putc(lz ? '0' : ' '); + while ((ch = *p++)) + putc(ch); + } + } + +abort: + va_end(va); + return 0; +} diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 4c82837..dd8380b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -861,6 +861,42 @@ int sprintf(char *buf, const char *fmt, ...) return i; }
+int printf(const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + va_start(args, fmt); + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); + va_end(args); + + /* Print the string */ + puts(printbuffer); + return i; +} + +int vprintf(const char *fmt, va_list args) +{ + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); + + /* Print the string */ + puts(printbuffer); + return i; +} + static void panic_finish(void) __attribute__ ((noreturn));
static void panic_finish(void)

On Mon, Nov 16, 2015 at 03:26:33PM +0100, Stefan Roese wrote:
This patch adds a small printf() version that supports all basic formats. Its intented to be used in U-Boot SPL versions on platforms with very limited internal RAM sizes.
To enable it, just define CONFIG_USE_TINY_PRINTF in your defconfig. This will result in the SPL using this tiny function and the main U-Boot still using the full-blown printf() function.
This code was copied from: http://www.sparetimelabs.com/printfrevisited With mostly only coding style related changes so that its checkpatch clean.
The size reduction is about 2.5KiB. Here a comparison for the db-mv784mp-gp (Marvell AXP) SPL:
Without this patch: 58963 18536 1928 79427 13643 ./spl/u-boot-spl
With this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
Note: To make it possible to compile tiny-printf.c instead of vsprintf.c when CONFIG_USE_TINY_PRINTF is defined, the functions printf() and vprintf() are moved from common/console.c into vsprintf.c in this patch.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net
This doesn't quite apply now, somehow and my attempt at making it apply was either somehow wrong, or there's other problems with the series: +(PMC440,lschlv2,zynq_zc702,zynq_zed,zynq_zc706,lsxhl,zynq_picozed,zynq_zybo) examples/a pi/vsprintf.o: In function `printf': +(PMC440,lschlv2,zynq_zc702,zynq_zed,zynq_zc706,lsxhl,zynq_picozed,zynq_zybo) build/../l ib/vsprintf.c:865: multiple definition of `printf' +(PMC440,lschlv2,zynq_zc702,zynq_zed,zynq_zc706,lsxhl,zynq_picozed,zynq_zybo) examples/a pi/libgenwrap.o:build/../examples/api/libgenwrap.c:23: first defined here
And smartweb has a longer and different failure.

Hi Tom,
On 21.11.2015 04:27, Tom Rini wrote:
On Mon, Nov 16, 2015 at 03:26:33PM +0100, Stefan Roese wrote:
This patch adds a small printf() version that supports all basic formats. Its intented to be used in U-Boot SPL versions on platforms with very limited internal RAM sizes.
To enable it, just define CONFIG_USE_TINY_PRINTF in your defconfig. This will result in the SPL using this tiny function and the main U-Boot still using the full-blown printf() function.
This code was copied from: http://www.sparetimelabs.com/printfrevisited With mostly only coding style related changes so that its checkpatch clean.
The size reduction is about 2.5KiB. Here a comparison for the db-mv784mp-gp (Marvell AXP) SPL:
Without this patch: 58963 18536 1928 79427 13643 ./spl/u-boot-spl
With this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
Note: To make it possible to compile tiny-printf.c instead of vsprintf.c when CONFIG_USE_TINY_PRINTF is defined, the functions printf() and vprintf() are moved from common/console.c into vsprintf.c in this patch.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net
This doesn't quite apply now, somehow and my attempt at making it apply was either somehow wrong, or there's other problems with the series: +(PMC440,lschlv2,zynq_zc702,zynq_zed,zynq_zc706,lsxhl,zynq_picozed,zynq_zybo) examples/a pi/vsprintf.o: In function `printf': +(PMC440,lschlv2,zynq_zc702,zynq_zed,zynq_zc706,lsxhl,zynq_picozed,zynq_zybo) build/../l ib/vsprintf.c:865: multiple definition of `printf' +(PMC440,lschlv2,zynq_zc702,zynq_zed,zynq_zc706,lsxhl,zynq_picozed,zynq_zybo) examples/a pi/libgenwrap.o:build/../examples/api/libgenwrap.c:23: first defined here
And smartweb has a longer and different failure.
Ah, thanks for checking. I hope that I've now fixed all issues with this tiny-printf implementation. v3 will follow shortly.
Thanks, Stefan

With this patch now, the tiny printf() function also supports numbers bigger than 0xffff. Additionally the code is simplified a bit and some static variables are moved to function parameters. Also the upper case hex variable output support is removed, as its not really needed in this simple printf version. And removing it reduces the complexity and the code size again a bit.
Here the new numbers, again on the db-mv784mp-gp (Armada XP):
Without this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
With this patch: 56446 18536 1936 76918 12c76 ./spl/u-boot-spl
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net --- v2: - new patch
lib/tiny-printf.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index d743a36..6766a8f 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -14,9 +14,6 @@ #include <serial.h>
static char *bf; -static char buf[12]; -static unsigned int num; -static char uc; static char zs;
static void out(char c) @@ -26,17 +23,16 @@ static void out(char c)
static void out_dgt(char dgt) { - out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10)); + out(dgt + (dgt < 10 ? '0' : 'a' - 10)); zs = 1; }
-static void div_out(unsigned int div) +static void div_out(unsigned int *num, unsigned int div) { unsigned char dgt = 0;
- num &= 0xffff; /* just for testing the code with 32 bit ints */ - while (num >= div) { - num -= div; + while (*num >= div) { + *num -= div; dgt++; }
@@ -49,6 +45,9 @@ int printf(const char *fmt, ...) va_list va; char ch; char *p; + unsigned int num; + char buf[12]; + unsigned int div;
va_start(va, fmt);
@@ -68,7 +67,7 @@ int printf(const char *fmt, ...) if (ch >= '0' && ch <= '9') { w = 0; while (ch >= '0' && ch <= '9') { - w = (((w << 2) + w) << 1) + ch - '0'; + w = (w * 10) + ch - '0'; ch = *fmt++; } } @@ -86,20 +85,13 @@ int printf(const char *fmt, ...) num = -(int)num; out('-'); } - div_out(10000); - div_out(1000); - div_out(100); - div_out(10); - out_dgt(num); + for (div = 1000000000; div; div /= 10) + div_out(&num, div); break; case 'x': - case 'X': - uc = ch == 'X'; num = va_arg(va, unsigned int); - div_out(0x1000); - div_out(0x100); - div_out(0x10); - out_dgt(num); + for (div = 0x10000000; div; div /= 0x10) + div_out(&num, div); break; case 'c': out((char)(va_arg(va, int)));

On Mon, Nov 16, 2015 at 03:26:34PM +0100, Stefan Roese wrote:
With this patch now, the tiny printf() function also supports numbers bigger than 0xffff. Additionally the code is simplified a bit and some static variables are moved to function parameters. Also the upper case hex variable output support is removed, as its not really needed in this simple printf version. And removing it reduces the complexity and the code size again a bit.
Here the new numbers, again on the db-mv784mp-gp (Armada XP):
Without this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
With this patch: 56446 18536 1936 76918 12c76 ./spl/u-boot-spl
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net
Applied to u-boot/master, thanks!

On 16 November 2015 at 07:26, Stefan Roese sr@denx.de wrote:
As done in commit da229e4e [sandbox: Drop special-case sandbox console code], this patch drops the sandbox special-case code in vprintf() that was missed by Simon at that time.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org
v2:
- new patch
common/console.c | 5 ----- 1 file changed, 5 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

This patch adds a small printf() version that supports all basic formats. Its intented to be used in U-Boot SPL versions on platforms with very limited internal RAM sizes.
To enable it, just define CONFIG_USE_TINY_PRINTF in your defconfig. This will result in the SPL using this tiny function and the main U-Boot still using the full-blown printf() function.
This code was copied from: http://www.sparetimelabs.com/printfrevisited With mostly only coding style related changes so that its checkpatch clean.
The size reduction is about 2.5KiB. Here a comparison for the db-mv784mp-gp (Marvell AXP) SPL:
Without this patch: 58963 18536 1928 79427 13643 ./spl/u-boot-spl
With this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
Note: To make it possible to compile tiny-printf.c instead of vsprintf.c when CONFIG_USE_TINY_PRINTF is defined, the functions printf() and vprintf() are moved from common/console.c into vsprintf.c in this patch.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net --- v3: - Rebased on latest master - Only compile files when CONFIG_SPL_SERIAL_SUPPORT is enabled (in SPL case) - Removed printf() / vprintf() from examples/api/libgenwrap.c as this code is now included in vsprintf.c
v2: - Patch split-up into multiple patches - Added comment about supported formats in Kconfig
common/console.c | 36 ------------- examples/api/libgenwrap.c | 40 ++------------ lib/Kconfig | 10 ++++ lib/Makefile | 13 ++++- lib/tiny-printf.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++ lib/vsprintf.c | 36 +++++++++++++ 6 files changed, 192 insertions(+), 73 deletions(-) create mode 100644 lib/tiny-printf.c
diff --git a/common/console.c b/common/console.c index 75f84bd..bc37b6d 100644 --- a/common/console.c +++ b/common/console.c @@ -558,42 +558,6 @@ void puts(const char *s) } }
-int printf(const char *fmt, ...) -{ - va_list args; - uint i; - char printbuffer[CONFIG_SYS_PBSIZE]; - - va_start(args, fmt); - - /* - * For this to work, printbuffer must be larger than - * anything we ever want to print. - */ - i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); - va_end(args); - - /* Print the string */ - puts(printbuffer); - return i; -} - -int vprintf(const char *fmt, va_list args) -{ - uint i; - char printbuffer[CONFIG_SYS_PBSIZE]; - - /* - * For this to work, printbuffer must be larger than - * anything we ever want to print. - */ - i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); - - /* Print the string */ - puts(printbuffer); - return i; -} - #ifdef CONFIG_CONSOLE_RECORD int console_record_init(void) { diff --git a/examples/api/libgenwrap.c b/examples/api/libgenwrap.c index c1afa5b..ba51007 100644 --- a/examples/api/libgenwrap.c +++ b/examples/api/libgenwrap.c @@ -16,46 +16,14 @@
#include "glue.h"
-/* - * printf() and vprintf() are stolen from u-boot/common/console.c - */ -int printf (const char *fmt, ...) -{ - va_list args; - uint i; - char printbuffer[256]; - - va_start (args, fmt); - - /* For this to work, printbuffer must be larger than - * anything we ever want to print. - */ - i = vsprintf (printbuffer, fmt, args); - va_end (args); - - /* Print the string */ - ub_puts (printbuffer); - return i; -} - -int vprintf (const char *fmt, va_list args) +void putc(const char c) { - uint i; - char printbuffer[256]; - - /* For this to work, printbuffer must be larger than - * anything we ever want to print. - */ - i = vsprintf (printbuffer, fmt, args); - - /* Print the string */ - ub_puts (printbuffer); - return i; + ub_putc(c); }
-void putc (const char c) +void puts(const char *s) { - ub_putc(c); + ub_puts(s); }
void __udelay(unsigned long usec) diff --git a/lib/Kconfig b/lib/Kconfig index 30e84ed..9d580e4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -36,6 +36,16 @@ config SYS_VSNPRINTF Thumb-2, about 420 bytes). Enable this option for safety when using sprintf() with data you do not control.
+config USE_TINY_PRINTF + bool "Enable tiny printf() version" + help + This option enables a tiny, stripped down printf version. + This should only be used in space limited environments, + like SPL versions with hard memory limits. This version + reduces the code size by about 2.5KiB on armv7. + + The supported format specifiers are %c, %s, %u/%d and %x. + config REGEX bool "Enable regular expression support" default y if NET diff --git a/lib/Makefile b/lib/Makefile index 6c36278..1f1ff6f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -80,7 +80,18 @@ obj-y += string.o obj-y += time.o obj-$(CONFIG_TRACE) += trace.o obj-$(CONFIG_LIB_UUID) += uuid.o -obj-y += vsprintf.o obj-$(CONFIG_LIB_RAND) += rand.o
+ifdef CONFIG_SPL_BUILD +# SPL U-Boot may use full-printf, tiny-printf or none at all +ifdef CONFIG_USE_TINY_PRINTF +obj-$(CONFIG_SPL_SERIAL_SUPPORT) += tiny-printf.o +else +obj-$(CONFIG_SPL_SERIAL_SUPPORT) += vsprintf.o +endif +else +# Main U-Boot always uses the full printf support +obj-y += vsprintf.o +endif + subdir-ccflags-$(CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED) += -O2 diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c new file mode 100644 index 0000000..d743a36 --- /dev/null +++ b/lib/tiny-printf.c @@ -0,0 +1,130 @@ +/* + * Tiny printf version for SPL + * + * Copied from: + * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php + * + * Copyright (C) 2004,2008 Kustaa Nyholm + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include <common.h> +#include <stdarg.h> +#include <serial.h> + +static char *bf; +static char buf[12]; +static unsigned int num; +static char uc; +static char zs; + +static void out(char c) +{ + *bf++ = c; +} + +static void out_dgt(char dgt) +{ + out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10)); + zs = 1; +} + +static void div_out(unsigned int div) +{ + unsigned char dgt = 0; + + num &= 0xffff; /* just for testing the code with 32 bit ints */ + while (num >= div) { + num -= div; + dgt++; + } + + if (zs || dgt > 0) + out_dgt(dgt); +} + +int printf(const char *fmt, ...) +{ + va_list va; + char ch; + char *p; + + va_start(va, fmt); + + while ((ch = *(fmt++))) { + if (ch != '%') { + putc(ch); + } else { + char lz = 0; + char w = 0; + + ch = *(fmt++); + if (ch == '0') { + ch = *(fmt++); + lz = 1; + } + + if (ch >= '0' && ch <= '9') { + w = 0; + while (ch >= '0' && ch <= '9') { + w = (((w << 2) + w) << 1) + ch - '0'; + ch = *fmt++; + } + } + bf = buf; + p = bf; + zs = 0; + + switch (ch) { + case 0: + goto abort; + case 'u': + case 'd': + num = va_arg(va, unsigned int); + if (ch == 'd' && (int)num < 0) { + num = -(int)num; + out('-'); + } + div_out(10000); + div_out(1000); + div_out(100); + div_out(10); + out_dgt(num); + break; + case 'x': + case 'X': + uc = ch == 'X'; + num = va_arg(va, unsigned int); + div_out(0x1000); + div_out(0x100); + div_out(0x10); + out_dgt(num); + break; + case 'c': + out((char)(va_arg(va, int))); + break; + case 's': + p = va_arg(va, char*); + break; + case '%': + out('%'); + default: + break; + } + + *bf = 0; + bf = p; + while (*bf++ && w > 0) + w--; + while (w-- > 0) + putc(lz ? '0' : ' '); + while ((ch = *p++)) + putc(ch); + } + } + +abort: + va_end(va); + return 0; +} diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 4c82837..dd8380b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -861,6 +861,42 @@ int sprintf(char *buf, const char *fmt, ...) return i; }
+int printf(const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + va_start(args, fmt); + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); + va_end(args); + + /* Print the string */ + puts(printbuffer); + return i; +} + +int vprintf(const char *fmt, va_list args) +{ + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); + + /* Print the string */ + puts(printbuffer); + return i; +} + static void panic_finish(void) __attribute__ ((noreturn));
static void panic_finish(void)

On Mon, Nov 23, 2015 at 07:00:22AM +0100, Stefan Roese wrote:
This patch adds a small printf() version that supports all basic formats. Its intented to be used in U-Boot SPL versions on platforms with very limited internal RAM sizes.
To enable it, just define CONFIG_USE_TINY_PRINTF in your defconfig. This will result in the SPL using this tiny function and the main U-Boot still using the full-blown printf() function.
This code was copied from: http://www.sparetimelabs.com/printfrevisited With mostly only coding style related changes so that its checkpatch clean.
The size reduction is about 2.5KiB. Here a comparison for the db-mv784mp-gp (Marvell AXP) SPL:
Without this patch: 58963 18536 1928 79427 13643 ./spl/u-boot-spl
With this patch: 56542 18536 1956 77034 12cea ./spl/u-boot-spl
Note: To make it possible to compile tiny-printf.c instead of vsprintf.c when CONFIG_USE_TINY_PRINTF is defined, the functions printf() and vprintf() are moved from common/console.c into vsprintf.c in this patch.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Cc: Hans de Goede hdegoede@redhat.com Cc: Tom Rini trini@konsulko.com Cc: Albert Aribaud albert.u.boot@aribaud.net
Applied to u-boot/master, thanks!

On Mon, Nov 16, 2015 at 03:26:31PM +0100, Stefan Roese wrote:
As done in commit da229e4e [sandbox: Drop special-case sandbox console code], this patch drops the sandbox special-case code in vprintf() that was missed by Simon at that time.
Signed-off-by: Stefan Roese sr@denx.de Cc: Simon Glass sjg@chromium.org Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/master, thanks!
participants (3)
-
Simon Glass
-
Stefan Roese
-
Tom Rini