Add support for the %pV format-specifier which allows printing a struct va_format. This is used by the Linux kernel for recursive printf() formatting and is needed by the ext4l filesystem driver. Add the struct to include/linux/printk.h to match the kernel location. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
354 lines
7.4 KiB
ReStructuredText
354 lines
7.4 KiB
ReStructuredText
.. 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.
|