From patchwork Wed Feb 4 00:09:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1796 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=1770163825; bh=ukR0qkx8LCGYWxtJnhrsBFEUKCqqlCQyriSLCEL6H34=; 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=w1zkE5Yf+8IACeTp59A0s+BR7XD5SL0ZsimQr8WFuKKTV8yz0Bu3G8ElafW3p/n3R Od2OMwGBNty5pePJTGX8Uls8VLF8DhlbpniRvQx7mWCduAboj0XbE6xLY0AIGNs3UX 4dUVNlqUDdK6eeyVwJj+OkAEz+P44yHQ+fbFHRKFxqW4PrngbisEWJdM9ALYXxwDK1 /3/il2Pnb1q6hOo0GupNa55tH3yxJbgOJU2SZcXohJpGszJdW5UGQSsIIy3wACmKhd q6+9OPR4KrSnb96CUb7oNxnwUkR97lequrVbSHGN6oRBhwmkuBb1hde3vS+vFSmOpC 5j/xBEd4LqXnw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E3ACA69917 for ; Tue, 3 Feb 2026 17:10: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 2ET8VW-KrQFJ for ; Tue, 3 Feb 2026 17:10:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1770163825; bh=ukR0qkx8LCGYWxtJnhrsBFEUKCqqlCQyriSLCEL6H34=; 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=w1zkE5Yf+8IACeTp59A0s+BR7XD5SL0ZsimQr8WFuKKTV8yz0Bu3G8ElafW3p/n3R Od2OMwGBNty5pePJTGX8Uls8VLF8DhlbpniRvQx7mWCduAboj0XbE6xLY0AIGNs3UX 4dUVNlqUDdK6eeyVwJj+OkAEz+P44yHQ+fbFHRKFxqW4PrngbisEWJdM9ALYXxwDK1 /3/il2Pnb1q6hOo0GupNa55tH3yxJbgOJU2SZcXohJpGszJdW5UGQSsIIy3wACmKhd q6+9OPR4KrSnb96CUb7oNxnwUkR97lequrVbSHGN6oRBhwmkuBb1hde3vS+vFSmOpC 5j/xBEd4LqXnw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D245569911 for ; Tue, 3 Feb 2026 17:10:25 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1770163825; bh=85vKIurHozCxZ+huyQ4eyfLMpf6ltggeL1WnouRTWDQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hHFVn/xdOZOEO9eQn8FuTOCRJ4bD1qM/Us1CBxL5foc51jEPCWMcF8UkVdtt0J0Yu aorY6b1gTWGCUbvQxJQumI5ToHpVExaO9xujvvb43SlhE5pTXEUuun3ffzHJu0Uhwv EoXKRiSjYGNF37WeNrhxnai3FY/LU/feM9BF2HvizxxWCjPoXOGph7kcPchV6yrDbE j+JfCnhb3bhUjDJvyB4xsSqlQXasvLa5g9HnSbMRHQGM6o5rZwyF0rDiw1BKK1zmPO SKZkiAuUHCZAY0sVNBbY8vNQT7mbk8i1pWfRC91Nj4r01i1zqMXA+htnmt19LG5EKS +A8rfWddf1Nyg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 09DA469868; Tue, 3 Feb 2026 17:10: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 10026) with ESMTP id K1CUcWwqGTty; Tue, 3 Feb 2026 17:10:24 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1770163820; bh=igHR0s76RuhOd/W+MqK3ytzOlHbqAe4sb0CxfZtb9Uc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r9lYwDG6S/vVqWyXbF/xFEm40siFaCNX55dMYJU10bn486nIvwZCYupsn/uTCI7rA l94kjtLHxTzr7ZfLC5RJ1bE2+/WlRTPmVKHGp7+ayKXp8JqGoGbfyW46oU3n44WwYA GP77Rk6Pl370AVIcYRlJ1VAtq9I/PQm9QedPHBZhZAaXrVwtdGWyNsBdjvPHKShC3i rWt+rf0F55DdZflfnOtALcTk2/EwwZFmSHMgb87OrILlQF+Lyvl3a3DWwsmdZXkEKH mjQTEWTQWzMTvix3XOpFCQxQxukJHlb5Gn9dB2Qo80rTxHf77rnAMXFI6V2adx2495 ZQtixLoywyumQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id A714169909; Tue, 3 Feb 2026 17:10:20 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Tue, 3 Feb 2026 17:09:46 -0700 Message-ID: <20260204001002.2638622-3-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260204001002.2638622-1-sjg@u-boot.org> References: <20260204001002.2638622-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: QDGQ752NEONISGX2CBVNIHYL2BT6PMQW X-Message-ID-Hash: QDGQ752NEONISGX2CBVNIHYL2BT6PMQW 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: Simon Glass , "Claude Sonnet 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 02/13] serial: Support length-based serial output 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 serial_putsn() to output a string with a specified length through the serial port. The serial uclass already supports length-based writes via __serial_puts(), so this just provides a public wrapper function. Add a test to check it. Co-developed-by: Claude Sonnet 4.5 Signed-off-by: Simon Glass --- drivers/serial/serial-uclass.c | 34 ++++++++++++++++++++++++++++++++++ include/serial.h | 12 ++++++++++++ test/dm/serial.c | 20 ++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 8d330d687a3..93fb4a0c2e3 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -309,6 +309,34 @@ static void _serial_puts(struct udevice *dev, const char *str) } while (*str); } +static void _serial_putsn(struct udevice *dev, const char *str, size_t len) +{ + struct dm_serial_ops *ops = serial_get_ops(dev); + + if (!CONFIG_IS_ENABLED(SERIAL_PUTS) || !ops->puts) { + while (len--) + _serial_putc(dev, *str++); + return; + } + + while (len) { + const char *newline = memchr(str, '\n', len); + size_t seg_len = newline ? newline - str : len; + + if (__serial_puts(dev, str, seg_len)) + return; + + if (newline && __serial_puts(dev, "\r\n", 2)) + return; + + if (IS_ENABLED(CONFIG_CONSOLE_FLUSH_ON_NEWLINE) && newline) + _serial_flush(dev); + + str += seg_len + !!newline; + len -= seg_len + !!newline; + } +} + static int __serial_getc(struct udevice *dev) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -391,6 +419,12 @@ void serial_puts(const char *str) _serial_puts(gd->cur_serial_dev, str); } +void serial_putsn(const char *str, int len) +{ + if (gd->cur_serial_dev) + _serial_putsn(gd->cur_serial_dev, str, len); +} + #ifdef CONFIG_CONSOLE_FLUSH_SUPPORT void serial_flush(void) { diff --git a/include/serial.h b/include/serial.h index 51977d8d7b7..66bf17a7cc0 100644 --- a/include/serial.h +++ b/include/serial.h @@ -392,6 +392,18 @@ void serial_setbrg(void); void serial_putc(const char ch); void serial_putc_raw(const char ch); void serial_puts(const char *str); + +/** + * serial_putsn() - Write a string with specified length to the serial console + * + * This outputs exactly @len characters from @str, regardless of any nul + * characters that may be present. This is useful for printing substrings or + * binary data that may contain embedded nuls. + * + * @str: String to output (need not be nul-terminated) + * @len: Number of characters to output + */ +void serial_putsn(const char *str, int len); #if defined(CONFIG_CONSOLE_FLUSH_SUPPORT) && CONFIG_IS_ENABLED(DM_SERIAL) void serial_flush(void); #else diff --git a/test/dm/serial.c b/test/dm/serial.c index 4acb14f41bc..8ed18726dd7 100644 --- a/test/dm/serial.c +++ b/test/dm/serial.c @@ -88,3 +88,23 @@ static int dm_test_serial(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_serial, UTF_SCAN_FDT); + +/* Test serial_putsn() function */ +static int dm_test_serial_putsn(struct unit_test_state *uts) +{ + const char *test_str = "testing string"; + size_t test_len = 4; + size_t start, written; + + /* Test that serial_putsn() writes the correct number of characters */ + sandbox_serial_endisable(false); + start = sandbox_serial_written(); + serial_putsn(test_str, test_len); + sandbox_serial_endisable(true); + + written = sandbox_serial_written() - start; + ut_asserteq(test_len, written); + + return 0; +} +DM_TEST(dm_test_serial_putsn, UTF_SCAN_FDT);