Skip to content

Commit 7d9cde1

Browse files
stroesetrini
authored andcommitted
lib/tiny-printf.c: Add tiny printf function for space limited environments
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>
1 parent ddf7355 commit 7d9cde1

6 files changed

Lines changed: 192 additions & 73 deletions

File tree

common/console.c

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -558,42 +558,6 @@ void puts(const char *s)
558558
}
559559
}
560560

561-
int printf(const char *fmt, ...)
562-
{
563-
va_list args;
564-
uint i;
565-
char printbuffer[CONFIG_SYS_PBSIZE];
566-
567-
va_start(args, fmt);
568-
569-
/*
570-
* For this to work, printbuffer must be larger than
571-
* anything we ever want to print.
572-
*/
573-
i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
574-
va_end(args);
575-
576-
/* Print the string */
577-
puts(printbuffer);
578-
return i;
579-
}
580-
581-
int vprintf(const char *fmt, va_list args)
582-
{
583-
uint i;
584-
char printbuffer[CONFIG_SYS_PBSIZE];
585-
586-
/*
587-
* For this to work, printbuffer must be larger than
588-
* anything we ever want to print.
589-
*/
590-
i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
591-
592-
/* Print the string */
593-
puts(printbuffer);
594-
return i;
595-
}
596-
597561
#ifdef CONFIG_CONSOLE_RECORD
598562
int console_record_init(void)
599563
{

examples/api/libgenwrap.c

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,46 +16,14 @@
1616

1717
#include "glue.h"
1818

19-
/*
20-
* printf() and vprintf() are stolen from u-boot/common/console.c
21-
*/
22-
int printf (const char *fmt, ...)
23-
{
24-
va_list args;
25-
uint i;
26-
char printbuffer[256];
27-
28-
va_start (args, fmt);
29-
30-
/* For this to work, printbuffer must be larger than
31-
* anything we ever want to print.
32-
*/
33-
i = vsprintf (printbuffer, fmt, args);
34-
va_end (args);
35-
36-
/* Print the string */
37-
ub_puts (printbuffer);
38-
return i;
39-
}
40-
41-
int vprintf (const char *fmt, va_list args)
19+
void putc(const char c)
4220
{
43-
uint i;
44-
char printbuffer[256];
45-
46-
/* For this to work, printbuffer must be larger than
47-
* anything we ever want to print.
48-
*/
49-
i = vsprintf (printbuffer, fmt, args);
50-
51-
/* Print the string */
52-
ub_puts (printbuffer);
53-
return i;
21+
ub_putc(c);
5422
}
5523

56-
void putc (const char c)
24+
void puts(const char *s)
5725
{
58-
ub_putc(c);
26+
ub_puts(s);
5927
}
6028

6129
void __udelay(unsigned long usec)

lib/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ config SYS_VSNPRINTF
3636
Thumb-2, about 420 bytes). Enable this option for safety when
3737
using sprintf() with data you do not control.
3838

39+
config USE_TINY_PRINTF
40+
bool "Enable tiny printf() version"
41+
help
42+
This option enables a tiny, stripped down printf version.
43+
This should only be used in space limited environments,
44+
like SPL versions with hard memory limits. This version
45+
reduces the code size by about 2.5KiB on armv7.
46+
47+
The supported format specifiers are %c, %s, %u/%d and %x.
48+
3949
config REGEX
4050
bool "Enable regular expression support"
4151
default y if NET

lib/Makefile

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,18 @@ obj-y += string.o
8080
obj-y += time.o
8181
obj-$(CONFIG_TRACE) += trace.o
8282
obj-$(CONFIG_LIB_UUID) += uuid.o
83-
obj-y += vsprintf.o
8483
obj-$(CONFIG_LIB_RAND) += rand.o
8584

85+
ifdef CONFIG_SPL_BUILD
86+
# SPL U-Boot may use full-printf, tiny-printf or none at all
87+
ifdef CONFIG_USE_TINY_PRINTF
88+
obj-$(CONFIG_SPL_SERIAL_SUPPORT) += tiny-printf.o
89+
else
90+
obj-$(CONFIG_SPL_SERIAL_SUPPORT) += vsprintf.o
91+
endif
92+
else
93+
# Main U-Boot always uses the full printf support
94+
obj-y += vsprintf.o
95+
endif
96+
8697
subdir-ccflags-$(CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED) += -O2

lib/tiny-printf.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Tiny printf version for SPL
3+
*
4+
* Copied from:
5+
* http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
6+
*
7+
* Copyright (C) 2004,2008 Kustaa Nyholm
8+
*
9+
* SPDX-License-Identifier: LGPL-2.1+
10+
*/
11+
12+
#include <common.h>
13+
#include <stdarg.h>
14+
#include <serial.h>
15+
16+
static char *bf;
17+
static char buf[12];
18+
static unsigned int num;
19+
static char uc;
20+
static char zs;
21+
22+
static void out(char c)
23+
{
24+
*bf++ = c;
25+
}
26+
27+
static void out_dgt(char dgt)
28+
{
29+
out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10));
30+
zs = 1;
31+
}
32+
33+
static void div_out(unsigned int div)
34+
{
35+
unsigned char dgt = 0;
36+
37+
num &= 0xffff; /* just for testing the code with 32 bit ints */
38+
while (num >= div) {
39+
num -= div;
40+
dgt++;
41+
}
42+
43+
if (zs || dgt > 0)
44+
out_dgt(dgt);
45+
}
46+
47+
int printf(const char *fmt, ...)
48+
{
49+
va_list va;
50+
char ch;
51+
char *p;
52+
53+
va_start(va, fmt);
54+
55+
while ((ch = *(fmt++))) {
56+
if (ch != '%') {
57+
putc(ch);
58+
} else {
59+
char lz = 0;
60+
char w = 0;
61+
62+
ch = *(fmt++);
63+
if (ch == '0') {
64+
ch = *(fmt++);
65+
lz = 1;
66+
}
67+
68+
if (ch >= '0' && ch <= '9') {
69+
w = 0;
70+
while (ch >= '0' && ch <= '9') {
71+
w = (((w << 2) + w) << 1) + ch - '0';
72+
ch = *fmt++;
73+
}
74+
}
75+
bf = buf;
76+
p = bf;
77+
zs = 0;
78+
79+
switch (ch) {
80+
case 0:
81+
goto abort;
82+
case 'u':
83+
case 'd':
84+
num = va_arg(va, unsigned int);
85+
if (ch == 'd' && (int)num < 0) {
86+
num = -(int)num;
87+
out('-');
88+
}
89+
div_out(10000);
90+
div_out(1000);
91+
div_out(100);
92+
div_out(10);
93+
out_dgt(num);
94+
break;
95+
case 'x':
96+
case 'X':
97+
uc = ch == 'X';
98+
num = va_arg(va, unsigned int);
99+
div_out(0x1000);
100+
div_out(0x100);
101+
div_out(0x10);
102+
out_dgt(num);
103+
break;
104+
case 'c':
105+
out((char)(va_arg(va, int)));
106+
break;
107+
case 's':
108+
p = va_arg(va, char*);
109+
break;
110+
case '%':
111+
out('%');
112+
default:
113+
break;
114+
}
115+
116+
*bf = 0;
117+
bf = p;
118+
while (*bf++ && w > 0)
119+
w--;
120+
while (w-- > 0)
121+
putc(lz ? '0' : ' ');
122+
while ((ch = *p++))
123+
putc(ch);
124+
}
125+
}
126+
127+
abort:
128+
va_end(va);
129+
return 0;
130+
}

lib/vsprintf.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,42 @@ int sprintf(char *buf, const char *fmt, ...)
861861
return i;
862862
}
863863

864+
int printf(const char *fmt, ...)
865+
{
866+
va_list args;
867+
uint i;
868+
char printbuffer[CONFIG_SYS_PBSIZE];
869+
870+
va_start(args, fmt);
871+
872+
/*
873+
* For this to work, printbuffer must be larger than
874+
* anything we ever want to print.
875+
*/
876+
i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
877+
va_end(args);
878+
879+
/* Print the string */
880+
puts(printbuffer);
881+
return i;
882+
}
883+
884+
int vprintf(const char *fmt, va_list args)
885+
{
886+
uint i;
887+
char printbuffer[CONFIG_SYS_PBSIZE];
888+
889+
/*
890+
* For this to work, printbuffer must be larger than
891+
* anything we ever want to print.
892+
*/
893+
i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
894+
895+
/* Print the string */
896+
puts(printbuffer);
897+
return i;
898+
}
899+
864900
static void panic_finish(void) __attribute__ ((noreturn));
865901

866902
static void panic_finish(void)

0 commit comments

Comments
 (0)