From patchwork Sun Dec 14 17:54:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 899 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734925; bh=WoNrmz8R6ISa9VDmkQ3cu7mc+uSQg21z1qYQFpLzZlg=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iMeMAH8kd2KAUeqOf6L71NismrjB96X5eBbcE0uinHY4HsT2/RhS2yaLOR/azUbVy WiKTTSVGez74APmYx/kIhRseUh/QADv29YKzNxg6yczuhpKUaDH3zlV18mzajnWoV4 rAst1XcuC155XNWGkD/lprkNUFXXkYLXAQO9B13ZLxKiDL9gXu4KQ5yDbuyDgpuOCG FRsIFWTnRnG944Mqf3m3wj3mrCnxxS1ipEn+9KcdPQIZbDahV0Vx3GU4J4F6ZUaynf abs1uJR1/Ge2BK5YFBdMnhtPAunUk3NZ3wus7zWPfKH+kOssSZ+fDK05CIaCeO0Ezi D6oJvexvkI15w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id CD74968A91 for ; Sun, 14 Dec 2025 10:55:25 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id rxEk1YOEKDiG for ; Sun, 14 Dec 2025 10:55:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734925; bh=WoNrmz8R6ISa9VDmkQ3cu7mc+uSQg21z1qYQFpLzZlg=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iMeMAH8kd2KAUeqOf6L71NismrjB96X5eBbcE0uinHY4HsT2/RhS2yaLOR/azUbVy WiKTTSVGez74APmYx/kIhRseUh/QADv29YKzNxg6yczuhpKUaDH3zlV18mzajnWoV4 rAst1XcuC155XNWGkD/lprkNUFXXkYLXAQO9B13ZLxKiDL9gXu4KQ5yDbuyDgpuOCG FRsIFWTnRnG944Mqf3m3wj3mrCnxxS1ipEn+9KcdPQIZbDahV0Vx3GU4J4F6ZUaynf abs1uJR1/Ge2BK5YFBdMnhtPAunUk3NZ3wus7zWPfKH+kOssSZ+fDK05CIaCeO0Ezi D6oJvexvkI15w== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id BCB7F68A96 for ; Sun, 14 Dec 2025 10:55:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734924; bh=SeHmOoO5JEyZuFDiQsS/AKuKQKd7qLKuAw/uHiDMLN0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E76JYsZTUG5rap61cFJ9JgmTMj04f3AqUFzC5w/6sBDU09zM5IQZXxPBQ832EYsYP r2yphqMhBuc+7LaZ4FFZD30QfGROx9ipXFJAg9gduNHqdoO3zqkWf8L2Ht/Mzyoanj mmgIuljEZaBpQ2YNDWtpuPJSyOtYpd+Sz65P3EZ48gaXP9u2Lzx0OER34L5dDZuKKM ReI4/YE528OfTHyAwKmx3ZeWLZncWMq1dDpcOQBqZbw36eAtXO5/HAq+VJB1Za3RJt OONpN96k4kDEFMqpnrRhqpayyvRzAOvvbnILbwFWpTXHvdaJvjEsY3MA5j1L2itwDX K/RMTc8GEfbKQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 14B5068A91; Sun, 14 Dec 2025 10:55:24 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 1PzAqR-zXxHs; Sun, 14 Dec 2025 10:55:23 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765734918; bh=DtH66KCcrWQglUFsBxSLExce6wNgyspFf1/PgdpW8N4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hCmLnv6N5j4tkeEuZZOv8o1ZCjCJ5yqmc8YATzAx51v6ev/1qVnD4l9hNyJKK4ay1 oHKSqCoa3iaqKB/g2pRZMbxUb55NCygC9Mjq25chI82YABhzyaVXM/oSAIqI2kkJ7i cGUWDmniL+fKQQdT1UXtJ/eZqqHYVjhCJMVIDhXwSEyZSJuH5dnC8GvTZ3Yi+TzFo1 PwMGR8DCPHniMDXP6DiXG+hLKfGduYEzvyz1l+1YVaR2kJ5I8GZjsWTurjB2bbRDV6 da/J89Ya8smktb2XyNcNFmbLvfRcOn6wp5eOy/iamqDSe0ibhqWNHogWM9TfVPYlmj OsgOYCi47oqOg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 16BD068A84; Sun, 14 Dec 2025 10:55:18 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 14 Dec 2025 10:54:28 -0700 Message-ID: <20251214175449.3799539-7-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251214175449.3799539-1-sjg@u-boot.org> References: <20251214175449.3799539-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 22LEJQ2EFUS466EJWKSF7VBIJBT5UXCX X-Message-ID-Hash: 22LEJQ2EFUS466EJWKSF7VBIJBT5UXCX X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 06/21] vsprintf: Add support for the %pV format-specifier List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass 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 Signed-off-by: Simon Glass --- doc/develop/printf.rst | 19 +++++++++++++++++ include/linux/printk.h | 5 +++++ lib/vsprintf.c | 12 +++++++++++ test/common/print.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst index edda8b24a8e..42de22c8555 100644 --- a/doc/develop/printf.rst +++ b/doc/develop/printf.rst @@ -258,6 +258,25 @@ Pointers 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 ----------- diff --git a/include/linux/printk.h b/include/linux/printk.h index 5e85513853c..e28cef0ac31 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -84,4 +84,9 @@ #define printk_once(fmt, ...) \ printk(fmt, ##__VA_ARGS__) +struct va_format { + const char *fmt; + va_list *va; +}; + #endif diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c072b44140b..0f2c303b138 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,6 +25,7 @@ #include #include #include +#include /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') @@ -508,6 +509,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, return uuid_string(buf, end, ptr, field_width, precision, flags, fmt); #endif + case 'V': + { + const struct va_format *vaf = ptr; + va_list va; + + va_copy(va, *vaf->va); + buf += vsnprintf(buf, end > buf ? end - buf : 0, + vaf->fmt, va); + va_end(va); + return buf; + } default: break; } diff --git a/test/common/print.c b/test/common/print.c index 3fe24dc3e9d..9bd409d4b66 100644 --- a/test/common/print.c +++ b/test/common/print.c @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -376,3 +378,49 @@ static int snprint(struct unit_test_state *uts) return 0; } COMMON_TEST(snprint, 0); + +/* Helper function to test %pV format specifier */ +static int print_with_va_format(char *buf, size_t size, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int ret; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + ret = snprintf(buf, size, "prefix: %pV :suffix", &vaf); + va_end(args); + + return ret; +} + +/* Test printing with %pV (struct va_format) */ +static int print_va_format(struct unit_test_state *uts) +{ + char str[64]; + int ret; + + /* Basic string */ + ret = print_with_va_format(str, sizeof(str), "hello"); + ut_asserteq_str("prefix: hello :suffix", str); + ut_asserteq(21, ret); + + /* String with arguments */ + ret = print_with_va_format(str, sizeof(str), "value=%d", 42); + ut_asserteq_str("prefix: value=42 :suffix", str); + ut_asserteq(24, ret); + + /* Multiple arguments */ + ret = print_with_va_format(str, sizeof(str), "%s: %d/%d", "test", 1, 2); + ut_asserteq_str("prefix: test: 1/2 :suffix", str); + ut_asserteq(25, ret); + + /* Truncation */ + ret = print_with_va_format(str, 15, "hello world"); + ut_asserteq_str("prefix: hello ", str); + ut_asserteq(27, ret); + + return 0; +} +COMMON_TEST(print_va_format, 0);