git: b1bef9f7e0e1 - main - linuxkpi: Add hex_dump_to_buffer()

From: Jean-Sébastien Pédron <dumbbell_at_FreeBSD.org>
Date: Sun, 04 Jan 2026 09:56:21 UTC
The branch main has been updated by dumbbell:

URL: https://cgit.FreeBSD.org/src/commit/?id=b1bef9f7e0e182a9eee222639ffc8af4883ec0fa

commit b1bef9f7e0e182a9eee222639ffc8af4883ec0fa
Author:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
AuthorDate: 2025-07-10 23:03:51 +0000
Commit:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
CommitDate: 2026-01-04 09:45:36 +0000

    linuxkpi: Add hex_dump_to_buffer()
    
    This function prints a single line of hex dump to the given line buffer.
    
    The implementation relies on `lkpi_hex_dump()` to format the string.
    
    Reviewed by:    bz
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D51559
---
 sys/compat/linuxkpi/common/include/linux/printk.h |  6 ++
 sys/compat/linuxkpi/common/src/linux_compat.c     | 70 +++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/printk.h b/sys/compat/linuxkpi/common/include/linux/printk.h
index e10656c8a1d0..066ec900f04e 100644
--- a/sys/compat/linuxkpi/common/include/linux/printk.h
+++ b/sys/compat/linuxkpi/common/include/linux/printk.h
@@ -50,6 +50,12 @@ void lkpi_hex_dump(int(*)(void *, const char *, ...), void *arg1,
     const char *, const char *, const int, const int, const int,
     const void *, size_t, const bool, const bool);
 
+#define	hex_dump_to_buffer(buf, len, rowsize, groupsize, linebuf, linebuflen, ascii) \
+    lkpi_hex_dump_to_buffer((buf), (len), (rowsize), (groupsize), (linebuf), (linebuflen), (ascii))
+
+int lkpi_hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+    int groupsize, char *linebuf, size_t linebuflen, bool ascii);
+
 static inline void
 print_hex_dump(const char *level, const char *prefix_str,
     const int prefix_type, const int rowsize, const int groupsize,
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index c2bad1f28eaf..8fc644241d79 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -1986,6 +1986,76 @@ lkpi_hex_dump(int(*_fpf)(void *, const char *, ...), void *arg1,
 	}
 }
 
+struct hdtb_context {
+	char	*linebuf;
+	size_t	 linebuflen;
+	int	 written;
+};
+
+static int
+hdtb_cb(void *arg, const char *format, ...)
+{
+	struct hdtb_context *context;
+	int written;
+	va_list args;
+
+	context = arg;
+
+	va_start(args, format);
+	written = vsnprintf(
+	    context->linebuf, context->linebuflen, format, args);
+	va_end(args);
+
+	if (written < 0)
+		return (written);
+
+	/*
+	 * Linux' hex_dump_to_buffer() function has the same behaviour as
+	 * snprintf() basically. Therefore, it returns the number of bytes it
+	 * would have written if the destination buffer was large enough.
+	 *
+	 * If the destination buffer was exhausted, lkpi_hex_dump() will
+	 * continue to call this callback but it will only compute the bytes it
+	 * would have written but write nothing to that buffer.
+	 */
+	context->written += written;
+
+	if (written < context->linebuflen) {
+		context->linebuf += written;
+		context->linebuflen -= written;
+	} else {
+		context->linebuf += context->linebuflen;
+		context->linebuflen = 0;
+	}
+
+	return (written);
+}
+
+int
+lkpi_hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+    int groupsize, char *linebuf, size_t linebuflen, bool ascii)
+{
+	int written;
+	struct hdtb_context context;
+
+	context.linebuf = linebuf;
+	context.linebuflen = linebuflen;
+	context.written = 0;
+
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	len = min(len, rowsize);
+
+	lkpi_hex_dump(
+	    hdtb_cb, &context, NULL, NULL, DUMP_PREFIX_NONE,
+	    rowsize, groupsize, buf, len, ascii, false);
+
+	written = context.written;
+
+	return (written);
+}
+
 static void
 linux_timer_callback_wrapper(void *context)
 {