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.