Printf-style Functions
U-Boot provides a family of printf-style functions for formatted output.
Functions
- printf()
Prints formatted output to the console.
int printf(const char *fmt, ...);
- vprintf()
Like printf() but takes a va_list argument.
int vprintf(const char *fmt, va_list args);
- sprintf()
Prints formatted output to a string buffer. The buffer must be large enough to hold the output.
int sprintf(char *buf, const char *fmt, ...);
- vsprintf()
Like sprintf() but takes a va_list argument.
int vsprintf(char *buf, const char *fmt, va_list args);
- snprintf()
Prints formatted output to a string buffer with a size limit. At most size-1 characters are written, and the buffer is always null-terminated. Returns the number of characters that would have been written if the buffer were large enough.
int snprintf(char *buf, size_t size, const char *fmt, ...);
- vsnprintf()
Like snprintf() but takes a va_list argument.
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
Format Specification
Each conversion specification consists of:
leading ‘%’ character
zero or more flags
an optional minimum field width
an optional precision field preceded by ‘.’
an optional length modifier
a conversion specifier
Flags
- ‘space’
fill up with spaces to reach the specified length
- -
left justify
- +
add sign field of decimal conversion
- #
convert to alternative form
prepend 0 to octal output
ignored for decimal output
prepend 0X to hexadecimal output
- 0
fill up with zeroes to reach the specified length
Integer types
Length modifiers
The optional length modifier specifies the size of the argument.
- no modifier
bool, enum, short, int are passed as int
- %h
convert to (unsigned) short before printing. Only the low 16 bits are printed.
- %hh
not implemented
- %j
not implemented
- %l
long
- %ll, %L
long long
- %t
ptr_diff_t
- %z, %Z
size_t, ssize_t
Conversion specifiers
Conversion specifiers control the output.
- %d
signed decimal
- %u
unsigned decimal
- %o
unsigned octal
- %x
unsigned lower case hexadecimal
- %X
unsigned upper case hexadecimal
The floating point conversion specifiers are not implemented:
%a
%A
%e
%E
%f
%F
%g
%G
The following tables shows the correct combinations of modifiers and specifiers for the individual integer types.
Type |
Format specifier |
|---|---|
bool |
%d, %x |
char |
%d, %x |
unsigned char |
%u, %x |
short |
%d, %x |
unsigned short |
%u, %x |
int |
%d, %x |
unsigned int |
%u, %x |
long |
%ld, %lx |
unsigned long |
%lu, %lx |
long long |
%lld, %llx |
unsigned long long |
%llu, %llx |
off_t |
%llu, %llx |
ptr_diff_t |
%td, %tx |
fdt_addr_t |
%pa, see pointers |
fdt_size_t |
%pa, see pointers |
phys_addr_t |
%pa, see pointers |
phys_size_t |
%pa, see pointers |
resource_size_t |
%pa, see pointers |
size_t |
%zu, %zx, %zX |
ssize_t |
%zd, %zx, %zX |
Characters
- %%
a ‘%’ character is written
- %c
prints a single character
- %lc
not implemented
Strings
- %s
prints a UTF-8 string (char *)
- %ls
prints a UTF-16 string (u16 *)
Pointers
- %p
prints the address the pointer points to hexadecimally
- %pa, %pap
prints the value of a phys_addr_t value that the pointer points to preceded with 0x and zero padding according to the size of phys_addr_t. The following types should be printed this way:
fdt_addr_t
fdt_size_t
phys_addr_t
phys_size_t
resource_size_t
- %pD
prints a UEFI device path (requires CONFIG_EFI_DEVICE_PATH_TO_TEXT)
- %pi4, %pI4
prints IPv4 address, e.g. ‘192.168.0.1’. Lower case (%pi4) omits the dot separators.
- %pi6, %pI6
prints IPv6 address (requires CONFIG_IPV6). Lower case (%pi6) omits the colon separators.
- %pm
prints MAC address without separators, e.g. ‘001122334455’
- %pM
print MAC address colon separated, e.g. ‘00:01:02:03:04:05’
- %pUb
prints GUID big endian, lower case (requires CONFIG_LIB_UUID) e.g. ‘00112233-4455-6677-8899-aabbccddeeff’
- %pUB
prints GUID big endian, upper case (requires CONFIG_LIB_UUID) e.g. ‘00112233-4455-6677-8899-AABBCCDDEEFF’
- %pUl
prints GUID little endian, lower case (requires CONFIG_LIB_UUID) e.g. ‘33221100-5544-7766-8899-aabbccddeeff’
- %pUL
prints GUID little endian, upper case (requires CONFIG_LIB_UUID) e.g. ‘33221100-5544-7766-8899-AABBCCDDEEFF’
- %pUs
prints text description of a GUID or if such is not known little endian, lower case (requires CONFIG_LIB_UUID), e.g. ‘system’ for a GUID identifying an EFI system partition.
- %pV
prints a struct va_format, which contains a format string and a va_list pointer. This allows recursive printf formatting and is used for implementing custom print functions that wrap printf.
void my_print(const char *fmt, ...) { struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; printf("prefix: %pV\n", &vaf); va_end(args); }
Tiny printf
For space-constrained environments like SPL, U-Boot provides a minimal printf implementation enabled by CONFIG_SPL_USE_TINY_PRINTF (and corresponding CONFIG_TPL_USE_TINY_PRINTF, CONFIG_VPL_USE_TINY_PRINTF for TPL and VPL). This reduces code size by approximately 2.5KiB on armv7.
The tiny printf supports only a limited set of format specifiers:
Basic specifiers
- %c
prints a single character
- %s
prints a string
- %d, %i
signed decimal integer
- %u
unsigned decimal integer
- %x
unsigned hexadecimal (lowercase)
- %%
a literal ‘%’ character
Length modifiers
- %l
long (e.g., %ld, %lu, %lx)
Width and padding
Field width and zero-padding are supported (e.g., %08x, %4d).
Pointer specifiers (CONFIG_SPL_NET only)
When CONFIG_SPL_NET is enabled, the following pointer formats are available:
- %pM
MAC address colon-separated, e.g. ‘00:11:22:33:44:55’
- %pm
MAC address without separators, e.g. ‘001122334455’
- %pI4
IPv4 address, e.g. ‘192.168.1.1’
Limitations
The tiny printf does NOT support:
Floating point (%f, %e, %g, etc.)
Long long (%ll)
Size/ptrdiff modifiers (%z, %t)
Precision (%.Nf, %.Ns)
Most pointer formats (%pU, %pD, %pV, etc.)
The snprintf() size parameter is ignored - no bounds checking is performed
Warning
Because snprintf() ignores the size parameter in tiny printf, buffer overflows are possible. Ensure buffers are large enough for the expected output.