.. SPDX-License-Identifier: GPL-2.0+ Printf-style Functions ====================== U-Boot provides a family of printf-style functions for formatted output. Functions --------- printf() Prints formatted output to the console. .. code-block:: c int printf(const char *fmt, ...); vprintf() Like printf() but takes a va_list argument. .. code-block:: c 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. .. code-block:: c int sprintf(char *buf, const char *fmt, ...); vsprintf() Like sprintf() but takes a va_list argument. .. code-block:: c 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. .. code-block:: c int snprintf(char *buf, size_t size, const char *fmt, ...); vsnprintf() Like snprintf() but takes a va_list argument. .. code-block:: c 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. .. code-block:: c 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.