All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH RESEND 0/2 v2] Introduce hexdump
@ 2016-06-10 12:42 Alexey Brodkin
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels Alexey Brodkin
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump Alexey Brodkin
  0 siblings, 2 replies; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-10 12:42 UTC (permalink / raw)
  To: u-boot

(Resending with real patches tagged bing v2)

This tiny series introduces functionality for either convertion a blob of data
to "hex ASCII" in memory or direct printing in stdout.

The first patch is required to safe existing users of dummy blobs
(as of today) that will become a real functions.

Note even though entire series is tagges as v2 

Cc: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>

Alexey Brodkin (2):
  linux-compat: Use original kern_levels.h for kernel debug levels
  lib: Add hexdump

Changes v1 -> v2:
 * Introduced linux/kern_levels.h so KERNEL_XXX symbols are really defined
 * Move hexdump definitions to a separate header.
 * Move helper funcions to the header so they might be used even if
   CONFIG_HEXDUMP is not enabled and if not used they will not occupy
   extra bytes of memory being "static inline" ones.
 * While at it replace its own hex_asc[], hex_asc_{lo|hi}() and
   pack_hex_byte() in lib/vsprintf.c with generic ones from hexdump.
 * In print_hex_dump() revert back first parametr for debug level,
   otherwise existing users of the function will be broken.

 include/common.h            |   1 +
 include/hexdump.h           | 108 ++++++++++++++++++++
 include/linux/compat.h      |  10 +-
 include/linux/kern_levels.h |  38 ++++++++
 lib/Kconfig                 |   5 +
 lib/Makefile                |   1 +
 lib/hexdump.c               | 233 ++++++++++++++++++++++++++++++++++++++++++++
 lib/vsprintf.c              |  17 +---
 8 files changed, 390 insertions(+), 23 deletions(-)
 create mode 100644 include/hexdump.h
 create mode 100644 include/linux/kern_levels.h
 create mode 100644 lib/hexdump.c

-- 
2.5.5

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels
  2016-06-10 12:42 [U-Boot] [PATCH RESEND 0/2 v2] Introduce hexdump Alexey Brodkin
@ 2016-06-10 12:42 ` Alexey Brodkin
  2016-06-10 19:20   ` Tom Rini
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump Alexey Brodkin
  1 sibling, 1 reply; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-10 12:42 UTC (permalink / raw)
  To: u-boot

Even currently in U-Boot we don't really use kernel debug levels
we do have quite a lot of code that was copy-pasted from Linux kernel
and so contains symbols like KERN_DEBUG and alike.

We used to just define those symbols which is fine if it is used in
constructions like:
----------------->8--------------
    printk(KERN_DEBUG "My debug message");
----------------->8--------------

But in other places where the symbol gets passed as a separate
argument (which we also have but luckily all of them are intself
dummy stubs in U-Boot) that won't work.

Now as a preparation to introduction of a real implementation of
print_hex_dump() we need those symbols to be defined as something real
so we're taking them as they are from Linux kernel.

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>
---

Changes v1 -> v2:
 * This patch was only introduced in v2.

 include/linux/compat.h      |  9 +--------
 include/linux/kern_levels.h | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 8 deletions(-)
 create mode 100644 include/linux/kern_levels.h

diff --git a/include/linux/compat.h b/include/linux/compat.h
index e561ee3..0ce7d65 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -28,14 +28,7 @@ extern struct p_current *current;
 #define printk	printf
 #define printk_once	printf
 
-#define KERN_EMERG
-#define KERN_ALERT
-#define KERN_CRIT
-#define KERN_ERR
-#define KERN_WARNING
-#define KERN_NOTICE
-#define KERN_INFO
-#define KERN_DEBUG
+#include <linux/kern_levels.h>
 
 #define GFP_ATOMIC ((gfp_t) 0)
 #define GFP_KERNEL ((gfp_t) 0)
diff --git a/include/linux/kern_levels.h b/include/linux/kern_levels.h
new file mode 100644
index 0000000..c2ce155
--- /dev/null
+++ b/include/linux/kern_levels.h
@@ -0,0 +1,38 @@
+#ifndef __KERN_LEVELS_H__
+#define __KERN_LEVELS_H__
+
+#define KERN_SOH	"\001"		/* ASCII Start Of Header */
+#define KERN_SOH_ASCII	'\001'
+
+#define KERN_EMERG	KERN_SOH "0"	/* system is unusable */
+#define KERN_ALERT	KERN_SOH "1"	/* action must be taken immediately */
+#define KERN_CRIT	KERN_SOH "2"	/* critical conditions */
+#define KERN_ERR	KERN_SOH "3"	/* error conditions */
+#define KERN_WARNING	KERN_SOH "4"	/* warning conditions */
+#define KERN_NOTICE	KERN_SOH "5"	/* normal but significant condition */
+#define KERN_INFO	KERN_SOH "6"	/* informational */
+#define KERN_DEBUG	KERN_SOH "7"	/* debug-level messages */
+
+#define KERN_DEFAULT	KERN_SOH "d"	/* the default kernel loglevel */
+
+/*
+ * Annotation for a "continued" line of log printout (only done after a
+ * line that had no enclosing \n). Only to be used by core/arch code
+ * during early bootup (a continued line is not SMP-safe otherwise).
+ */
+#define KERN_CONT	""
+
+/* integer equivalents of KERN_<LEVEL> */
+#define LOGLEVEL_SCHED		-2	/* Deferred messages from sched code
+					 * are set to this special level */
+#define LOGLEVEL_DEFAULT	-1	/* default (or last) loglevel */
+#define LOGLEVEL_EMERG		0	/* system is unusable */
+#define LOGLEVEL_ALERT		1	/* action must be taken immediately */
+#define LOGLEVEL_CRIT		2	/* critical conditions */
+#define LOGLEVEL_ERR		3	/* error conditions */
+#define LOGLEVEL_WARNING	4	/* warning conditions */
+#define LOGLEVEL_NOTICE		5	/* normal but significant condition */
+#define LOGLEVEL_INFO		6	/* informational */
+#define LOGLEVEL_DEBUG		7	/* debug-level messages */
+
+#endif
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 12:42 [U-Boot] [PATCH RESEND 0/2 v2] Introduce hexdump Alexey Brodkin
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels Alexey Brodkin
@ 2016-06-10 12:42 ` Alexey Brodkin
  2016-06-10 15:31   ` Langer, Thomas
  2016-06-10 19:22   ` Tom Rini
  1 sibling, 2 replies; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-10 12:42 UTC (permalink / raw)
  To: u-boot

Often during debugging session it's very interesting to see
what data we were dealing with. For example what we write or read
to/from memory or peripherals.

This change introduces functions that allow to dump binary
data with one simple function invocation like:
------------------->8----------------
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
------------------->8----------------

which gives us the following:
------------------->8----------------
00000000: f2 b7 c9 88 62 61 75 64 72 61 74 65 3d 31 31 35  ....baudrate=115
00000010: 32 30 30 00 62 6f 6f 74 61 72 67 73 3d 63 6f 6e  200.bootargs=con
00000020: 73 6f 6c 65 3d 74 74 79 53 33 2c 31 31 35 32 30  sole=ttyS3,11520
00000030: 30 6e 38 00 62 6f 6f 74 64 65 6c 61 79 3d 33 00  0n8.bootdelay=3.
00000040: 62 6f 6f 74 66 69 6c 65 3d 75 49 6d 61 67 65 00  bootfile=uImage.
00000050: 66 64 74 63 6f 6e 74 72 6f 6c 61 64 64 72 3d 39  fdtcontroladdr=9
00000060: 66 66 62 31 62 61 30 00 6c 6f 61 64 61 64 64 72  ffb1ba0.loadaddr
00000070: 3d 30 78 38 32 30 30 30 30 30 30 00 73 74 64 65  =0x82000000.stde
00000080: 72 72 3d 73 65 72 69 61 6c 30 40 65 30 30 32 32  rr=serial0 at e0022
00000090: 30 30 30 00 73 74 64 69 6e 3d 73 65 72 69 61 6c  000.stdin=serial
000000a0: 30 40 65 30 30 32 32 30 30 30 00 73 74 64 6f 75  0 at e0022000.stdou
000000b0: 74 3d 73 65 72 69 61 6c 30 40 65 30 30 32 32 30  t=serial0 at e00220
000000c0: 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00..............
...
------------------->8----------------

Source of hexdump.c was copied from Linux kernel v4.7-rc2.

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Reviewed-by: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>

---

Changes v1 -> v2:
 * Move hexdump definitions to a separate header.
 * Move helper funcions to the header so they might be used even if
   CONFIG_HEXDUMP is not enabled and if not used they will not occupy
   extra bytes of memory being "static inline" ones.
 * While at it replace its own hex_asc[], hex_asc_{lo|hi}() and
   pack_hex_byte() in lib/vsprintf.c with generic ones from hexdump.
 * In print_hex_dump() revert back first parametr for debug level,
   otherwise existing users of the function will be broken.

 include/common.h       |   1 +
 include/hexdump.h      | 108 +++++++++++++++++++++++
 include/linux/compat.h |   1 -
 lib/Kconfig            |   5 ++
 lib/Makefile           |   1 +
 lib/hexdump.c          | 233 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/vsprintf.c         |  17 +---
 7 files changed, 351 insertions(+), 15 deletions(-)
 create mode 100644 include/hexdump.h
 create mode 100644 lib/hexdump.c

diff --git a/include/common.h b/include/common.h
index f9f4605..51a438c 100644
--- a/include/common.h
+++ b/include/common.h
@@ -23,6 +23,7 @@ typedef volatile unsigned char	vu_char;
 #include <linux/stringify.h>
 #include <asm/ptrace.h>
 #include <stdarg.h>
+#include <hexdump.h>
 #include <linux/kernel.h>
 #if defined(CONFIG_PCI) && defined(CONFIG_4xx)
 #include <pci.h>
diff --git a/include/hexdump.h b/include/hexdump.h
new file mode 100644
index 0000000..de2e565
--- /dev/null
+++ b/include/hexdump.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef HEXDUMP_H
+#define HEXDUMP_H
+
+#include <linux/ctype.h>
+
+enum {
+	DUMP_PREFIX_NONE,
+	DUMP_PREFIX_ADDRESS,
+	DUMP_PREFIX_OFFSET
+};
+
+extern const char hex_asc[];
+#define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
+
+static inline char *hex_byte_pack(char *buf, u8 byte)
+{
+	*buf++ = hex_asc_hi(byte);
+	*buf++ = hex_asc_lo(byte);
+	return buf;
+}
+
+/**
+ * hex_to_bin - convert a hex digit to its real value
+ * @ch: ascii character represents hex digit
+ *
+ * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
+ * input.
+ */
+static inline int hex_to_bin(char ch)
+{
+	if ((ch >= '0') && (ch <= '9'))
+		return ch - '0';
+	ch = tolower(ch);
+	if ((ch >= 'a') && (ch <= 'f'))
+		return ch - 'a' + 10;
+	return -1;
+}
+
+/**
+ * hex2bin - convert an ascii hexadecimal string to its binary representation
+ * @dst: binary result
+ * @src: ascii hexadecimal string
+ * @count: result length
+ *
+ * Return 0 on success, -1 in case of bad input.
+ */
+static inline int hex2bin(u8 *dst, const char *src, size_t count)
+{
+	while (count--) {
+		int hi = hex_to_bin(*src++);
+		int lo = hex_to_bin(*src++);
+
+		if ((hi < 0) || (lo < 0))
+			return -1;
+
+		*dst++ = (hi << 4) | lo;
+	}
+	return 0;
+}
+
+/**
+ * bin2hex - convert binary data to an ascii hexadecimal string
+ * @dst: ascii hexadecimal result
+ * @src: binary data
+ * @count: binary data length
+ */
+static inline char *bin2hex(char *dst, const void *src, size_t count)
+{
+	const unsigned char *_src = src;
+
+	while (count--)
+		dst = hex_byte_pack(dst, *_src++);
+	return dst;
+}
+
+
+#ifdef CONFIG_HEXDUMP
+int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
+		       char *linebuf, size_t linebuflen, bool ascii);
+void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
+		    int rowsize, int groupsize, const void *buf, size_t len,
+		    bool ascii);
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+			  const void *buf, size_t len);
+#else /* !CONFIG_HEXDUMP */
+/*
+ * Some code in U-Boot copy-pasted from Linux kernel uses both
+ * functions below so to keep stuff compilable we keep these stubs here.
+ */
+static inline void print_hex_dump(const char *level, const char *prefix_str,
+				  int prefix_type, int rowsize, int groupsize,
+				  const void *buf, size_t len, bool ascii)
+{
+}
+static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+					const void *buf, size_t len)
+{
+}
+#endif /* CONFIG_HEXDUMP */
+
+#endif /* HEXDUMP_H */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 0ce7d65..074a85e 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -193,7 +193,6 @@ typedef unsigned long blkcnt_t;
 #define init_waitqueue_head(...)	do { } while (0)
 #define wait_event_interruptible(...)	0
 #define wake_up_interruptible(...)	do { } while (0)
-#define print_hex_dump(...)		do { } while (0)
 #define dump_stack(...)			do { } while (0)
 
 #define task_pid_nr(x)			0
diff --git a/lib/Kconfig b/lib/Kconfig
index 2b97c2b..a563b5e 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -128,6 +128,11 @@ config ERRNO_STR
 	  - if errno is null or positive number - a pointer to "Success" message
 	  - if errno is negative - a pointer to errno related message
 
+config HEXDUMP
+	bool "Enable hexdump"
+	help
+	  This enables functions for printing dumps of binary data.
+
 config OF_LIBFDT
 	bool "Enable the FDT library"
 	default y if OF_CONTROL
diff --git a/lib/Makefile b/lib/Makefile
index 02dfa29..1bf7c37 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -76,6 +76,7 @@ obj-y += membuff.o
 obj-$(CONFIG_REGEX) += slre.o
 obj-y += string.o
 obj-y += time.o
+obj-y += hexdump.o
 obj-$(CONFIG_TRACE) += trace.o
 obj-$(CONFIG_LIB_UUID) += uuid.o
 obj-$(CONFIG_LIB_RAND) += rand.o
diff --git a/lib/hexdump.c b/lib/hexdump.c
new file mode 100644
index 0000000..ffee5ce
--- /dev/null
+++ b/lib/hexdump.c
@@ -0,0 +1,233 @@
+/*
+ * lib/hexdump.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <common.h>
+#include <linux/ctype.h>
+#include <linux/compat.h>
+#include <linux/log2.h>
+#include <asm/unaligned.h>
+
+const char hex_asc[] = "0123456789abcdef";
+const char hex_asc_upper[] = "0123456789ABCDEF";
+
+#ifdef CONFIG_HEXDUMP
+/**
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
+ *
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ *			linebuf, sizeof(linebuf), true);
+ *
+ * example output buffer:
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
+ *
+ * Return:
+ * The amount of bytes placed in the buffer without terminating NUL. If the
+ * output was truncated, then the return value is the number of bytes
+ * (excluding the terminating NUL) which would have been written to the final
+ * string if enough space had been available.
+ */
+int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize,
+		       char *linebuf, size_t linebuflen, bool ascii)
+{
+	const u8 *ptr = buf;
+	int ngroups;
+	u8 ch;
+	int j, lx = 0;
+	int ascii_column;
+	int ret;
+
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	if (len > rowsize)		/* limit to one line at a time */
+		len = rowsize;
+	if (!is_power_of_2(groupsize) || groupsize > 8)
+		groupsize = 1;
+	if ((len % groupsize) != 0)	/* no mixed size output */
+		groupsize = 1;
+
+	ngroups = len / groupsize;
+	ascii_column = rowsize * 2 + rowsize / groupsize + 1;
+
+	if (!linebuflen)
+		goto overflow1;
+
+	if (!len)
+		goto nil;
+
+	if (groupsize == 8) {
+		const u64 *ptr8 = buf;
+
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%16.16llx", j ? " " : "",
+				       get_unaligned(ptr8 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
+	} else if (groupsize == 4) {
+		const u32 *ptr4 = buf;
+
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%8.8x", j ? " " : "",
+				       get_unaligned(ptr4 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
+	} else if (groupsize == 2) {
+		const u16 *ptr2 = buf;
+
+		for (j = 0; j < ngroups; j++) {
+			ret = snprintf(linebuf + lx, linebuflen - lx,
+				       "%s%4.4x", j ? " " : "",
+				       get_unaligned(ptr2 + j));
+			if (ret >= linebuflen - lx)
+				goto overflow1;
+			lx += ret;
+		}
+	} else {
+		for (j = 0; j < len; j++) {
+			if (linebuflen < lx + 2)
+				goto overflow2;
+			ch = ptr[j];
+			linebuf[lx++] = hex_asc_hi(ch);
+			if (linebuflen < lx + 2)
+				goto overflow2;
+			linebuf[lx++] = hex_asc_lo(ch);
+			if (linebuflen < lx + 2)
+				goto overflow2;
+			linebuf[lx++] = ' ';
+		}
+		if (j)
+			lx--;
+	}
+	if (!ascii)
+		goto nil;
+
+	while (lx < ascii_column) {
+		if (linebuflen < lx + 2)
+			goto overflow2;
+		linebuf[lx++] = ' ';
+	}
+	for (j = 0; j < len; j++) {
+		if (linebuflen < lx + 2)
+			goto overflow2;
+		ch = ptr[j];
+		linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
+	}
+nil:
+	linebuf[lx] = '\0';
+	return lx;
+overflow2:
+	linebuf[lx++] = '\0';
+overflow1:
+	return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
+}
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_str: string to prefix each line with;
+ *  caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the kernel log at the specified kernel log level, with an optional
+ * leading prefix.
+ *
+ * print_hex_dump() works on one "line" of output@a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
+ *
+ * E.g.:
+ *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ *		    16, 1, frame->data, frame->len, true);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c  pqrstuvwxyz{|}~.
+ */
+void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
+		    int rowsize, int groupsize,
+		    const void *buf, size_t len, bool ascii)
+{
+	const u8 *ptr = buf;
+	int i, linelen, remaining = len;
+	char linebuf[32 * 3 + 2 + 32 + 1];
+
+	if (rowsize != 16 && rowsize != 32)
+		rowsize = 16;
+
+	for (i = 0; i < len; i += rowsize) {
+		linelen = min(remaining, rowsize);
+		remaining -= rowsize;
+
+		hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+				   linebuf, sizeof(linebuf), ascii);
+
+		switch (prefix_type) {
+		case DUMP_PREFIX_ADDRESS:
+			printf("%s%p: %s\n", prefix_str, ptr + i, linebuf);
+			break;
+		case DUMP_PREFIX_OFFSET:
+			printf("%s%.8x: %s\n", prefix_str, i, linebuf);
+			break;
+		default:
+			printf("%s%s\n", prefix_str, linebuf);
+			break;
+		}
+	}
+}
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ *  caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+			  const void *buf, size_t len)
+{
+	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+		       buf, len, true);
+}
+
+#endif /* CONFIG_HEXDUMP */
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 874a295..c0a0aaa 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -271,17 +271,6 @@ static char *string(char *buf, char *end, char *s, int field_width,
 }
 
 #ifdef CONFIG_CMD_NET
-static const char hex_asc[] = "0123456789abcdef";
-#define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
-#define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
-
-static inline char *pack_hex_byte(char *buf, u8 byte)
-{
-	*buf++ = hex_asc_hi(byte);
-	*buf++ = hex_asc_lo(byte);
-	return buf;
-}
-
 static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
 				int precision, int flags)
 {
@@ -291,7 +280,7 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
 	int i;
 
 	for (i = 0; i < 6; i++) {
-		p = pack_hex_byte(p, addr[i]);
+		p = hex_byte_pack(p, addr[i]);
 		if (!(flags & SPECIAL) && i != 5)
 			*p++ = ':';
 	}
@@ -310,8 +299,8 @@ static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
 	int i;
 
 	for (i = 0; i < 8; i++) {
-		p = pack_hex_byte(p, addr[2 * i]);
-		p = pack_hex_byte(p, addr[2 * i + 1]);
+		p = hex_byte_pack(p, addr[2 * i]);
+		p = hex_byte_pack(p, addr[2 * i + 1]);
 		if (!(flags & SPECIAL) && i != 7)
 			*p++ = ':';
 	}
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump Alexey Brodkin
@ 2016-06-10 15:31   ` Langer, Thomas
  2016-06-10 19:37     ` Tom Rini
  2016-06-10 19:22   ` Tom Rini
  1 sibling, 1 reply; 15+ messages in thread
From: Langer, Thomas @ 2016-06-10 15:31 UTC (permalink / raw)
  To: u-boot

Hello Alexey,

This feature is already available in u-boot, please look for 'print_buffer'.

Best regards,
Thomas

> -----Original Message-----
> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Alexey
> Brodkin
> Sent: Friday, June 10, 2016 2:43 PM
> To: u-boot at lists.denx.de
> Cc: Tom Rini <trini@konsulko.com>; Alexey Brodkin
> <Alexey.Brodkin@synopsys.com>
> Subject: [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
> 
> Often during debugging session it's very interesting to see
> what data we were dealing with. For example what we write or read
> to/from memory or peripherals.
> 
> This change introduces functions that allow to dump binary
> data with one simple function invocation like:
> ------------------->8----------------
> print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
> ------------------->8----------------
> 
> which gives us the following:
> ------------------->8----------------
> 00000000: f2 b7 c9 88 62 61 75 64 72 61 74 65 3d 31 31 35  ....baudrate=115
> 00000010: 32 30 30 00 62 6f 6f 74 61 72 67 73 3d 63 6f 6e  200.bootargs=con
> 00000020: 73 6f 6c 65 3d 74 74 79 53 33 2c 31 31 35 32 30  sole=ttyS3,11520
> 00000030: 30 6e 38 00 62 6f 6f 74 64 65 6c 61 79 3d 33 00  0n8.bootdelay=3.
> 00000040: 62 6f 6f 74 66 69 6c 65 3d 75 49 6d 61 67 65 00  bootfile=uImage.
> 00000050: 66 64 74 63 6f 6e 74 72 6f 6c 61 64 64 72 3d 39  fdtcontroladdr=9
> 00000060: 66 66 62 31 62 61 30 00 6c 6f 61 64 61 64 64 72  ffb1ba0.loadaddr
> 00000070: 3d 30 78 38 32 30 30 30 30 30 30 00 73 74 64 65
> =0x82000000.stde
> 00000080: 72 72 3d 73 65 72 69 61 6c 30 40 65 30 30 32 32
> rr=serial0 at e0022
> 00000090: 30 30 30 00 73 74 64 69 6e 3d 73 65 72 69 61 6c  000.stdin=serial
> 000000a0: 30 40 65 30 30 32 32 30 30 30 00 73 74 64 6f 75
> 0 at e0022000.stdou
> 000000b0: 74 3d 73 65 72 69 61 6c 30 40 65 30 30 32 32 30
> t=serial0 at e00220
> 000000c0: 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00..............
> ...
> ------------------->8----------------
> 
> Source of hexdump.c was copied from Linux kernel v4.7-rc2.
> 
> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> Reviewed-by: Stefan Roese <sr@denx.de>
> Cc: Tom Rini <trini@konsulko.com>
> 
> ---
> 
> Changes v1 -> v2:
>  * Move hexdump definitions to a separate header.
>  * Move helper funcions to the header so they might be used even if
>    CONFIG_HEXDUMP is not enabled and if not used they will not occupy
>    extra bytes of memory being "static inline" ones.
>  * While at it replace its own hex_asc[], hex_asc_{lo|hi}() and
>    pack_hex_byte() in lib/vsprintf.c with generic ones from hexdump.
>  * In print_hex_dump() revert back first parametr for debug level,
>    otherwise existing users of the function will be broken.
> 
>  include/common.h       |   1 +
>  include/hexdump.h      | 108 +++++++++++++++++++++++
>  include/linux/compat.h |   1 -
>  lib/Kconfig            |   5 ++
>  lib/Makefile           |   1 +
>  lib/hexdump.c          | 233
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/vsprintf.c         |  17 +---
>  7 files changed, 351 insertions(+), 15 deletions(-)
>  create mode 100644 include/hexdump.h
>  create mode 100644 lib/hexdump.c
> 
> diff --git a/include/common.h b/include/common.h
> index f9f4605..51a438c 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -23,6 +23,7 @@ typedef volatile unsigned char	vu_char;
>  #include <linux/stringify.h>
>  #include <asm/ptrace.h>
>  #include <stdarg.h>
> +#include <hexdump.h>
>  #include <linux/kernel.h>
>  #if defined(CONFIG_PCI) && defined(CONFIG_4xx)
>  #include <pci.h>
> diff --git a/include/hexdump.h b/include/hexdump.h
> new file mode 100644
> index 0000000..de2e565
> --- /dev/null
> +++ b/include/hexdump.h
> @@ -0,0 +1,108 @@
> +/*
> + * Copyright (C) 2016 Synopsys, Inc. All rights reserved.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef HEXDUMP_H
> +#define HEXDUMP_H
> +
> +#include <linux/ctype.h>
> +
> +enum {
> +	DUMP_PREFIX_NONE,
> +	DUMP_PREFIX_ADDRESS,
> +	DUMP_PREFIX_OFFSET
> +};
> +
> +extern const char hex_asc[];
> +#define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
> +#define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
> +
> +static inline char *hex_byte_pack(char *buf, u8 byte)
> +{
> +	*buf++ = hex_asc_hi(byte);
> +	*buf++ = hex_asc_lo(byte);
> +	return buf;
> +}
> +
> +/**
> + * hex_to_bin - convert a hex digit to its real value
> + * @ch: ascii character represents hex digit
> + *
> + * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
> + * input.
> + */
> +static inline int hex_to_bin(char ch)
> +{
> +	if ((ch >= '0') && (ch <= '9'))
> +		return ch - '0';
> +	ch = tolower(ch);
> +	if ((ch >= 'a') && (ch <= 'f'))
> +		return ch - 'a' + 10;
> +	return -1;
> +}
> +
> +/**
> + * hex2bin - convert an ascii hexadecimal string to its binary representation
> + * @dst: binary result
> + * @src: ascii hexadecimal string
> + * @count: result length
> + *
> + * Return 0 on success, -1 in case of bad input.
> + */
> +static inline int hex2bin(u8 *dst, const char *src, size_t count)
> +{
> +	while (count--) {
> +		int hi = hex_to_bin(*src++);
> +		int lo = hex_to_bin(*src++);
> +
> +		if ((hi < 0) || (lo < 0))
> +			return -1;
> +
> +		*dst++ = (hi << 4) | lo;
> +	}
> +	return 0;
> +}
> +
> +/**
> + * bin2hex - convert binary data to an ascii hexadecimal string
> + * @dst: ascii hexadecimal result
> + * @src: binary data
> + * @count: binary data length
> + */
> +static inline char *bin2hex(char *dst, const void *src, size_t count)
> +{
> +	const unsigned char *_src = src;
> +
> +	while (count--)
> +		dst = hex_byte_pack(dst, *_src++);
> +	return dst;
> +}
> +
> +
> +#ifdef CONFIG_HEXDUMP
> +int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int
> groupsize,
> +		       char *linebuf, size_t linebuflen, bool ascii);
> +void print_hex_dump(const char *level, const char *prefix_str, int
> prefix_type,
> +		    int rowsize, int groupsize, const void *buf, size_t len,
> +		    bool ascii);
> +void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
> +			  const void *buf, size_t len);
> +#else /* !CONFIG_HEXDUMP */
> +/*
> + * Some code in U-Boot copy-pasted from Linux kernel uses both
> + * functions below so to keep stuff compilable we keep these stubs here.
> + */
> +static inline void print_hex_dump(const char *level, const char *prefix_str,
> +				  int prefix_type, int rowsize, int groupsize,
> +				  const void *buf, size_t len, bool ascii)
> +{
> +}
> +static inline void print_hex_dump_bytes(const char *prefix_str, int
> prefix_type,
> +					const void *buf, size_t len)
> +{
> +}
> +#endif /* CONFIG_HEXDUMP */
> +
> +#endif /* HEXDUMP_H */
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index 0ce7d65..074a85e 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -193,7 +193,6 @@ typedef unsigned long blkcnt_t;
>  #define init_waitqueue_head(...)	do { } while (0)
>  #define wait_event_interruptible(...)	0
>  #define wake_up_interruptible(...)	do { } while (0)
> -#define print_hex_dump(...)		do { } while (0)
>  #define dump_stack(...)			do { } while (0)
> 
>  #define task_pid_nr(x)			0
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 2b97c2b..a563b5e 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -128,6 +128,11 @@ config ERRNO_STR
>  	  - if errno is null or positive number - a pointer to "Success" message
>  	  - if errno is negative - a pointer to errno related message
> 
> +config HEXDUMP
> +	bool "Enable hexdump"
> +	help
> +	  This enables functions for printing dumps of binary data.
> +
>  config OF_LIBFDT
>  	bool "Enable the FDT library"
>  	default y if OF_CONTROL
> diff --git a/lib/Makefile b/lib/Makefile
> index 02dfa29..1bf7c37 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -76,6 +76,7 @@ obj-y += membuff.o
>  obj-$(CONFIG_REGEX) += slre.o
>  obj-y += string.o
>  obj-y += time.o
> +obj-y += hexdump.o
>  obj-$(CONFIG_TRACE) += trace.o
>  obj-$(CONFIG_LIB_UUID) += uuid.o
>  obj-$(CONFIG_LIB_RAND) += rand.o
> diff --git a/lib/hexdump.c b/lib/hexdump.c
> new file mode 100644
> index 0000000..ffee5ce
> --- /dev/null
> +++ b/lib/hexdump.c
> @@ -0,0 +1,233 @@
> +/*
> + * lib/hexdump.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation. See README and COPYING
> for
> + * more details.
> + */
> +
> +#include <common.h>
> +#include <linux/ctype.h>
> +#include <linux/compat.h>
> +#include <linux/log2.h>
> +#include <asm/unaligned.h>
> +
> +const char hex_asc[] = "0123456789abcdef";
> +const char hex_asc_upper[] = "0123456789ABCDEF";
> +
> +#ifdef CONFIG_HEXDUMP
> +/**
> + * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + * @rowsize: number of bytes to print per line; must be 16 or 32
> + * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
> + * @linebuf: where to put the converted data
> + * @linebuflen: total size of @linebuf, including space for terminating NUL
> + * @ascii: include ASCII after the hex output
> + *
> + * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
> + * 16 or 32 bytes of input data converted to hex + ASCII output.
> + *
> + * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
> + * to a hex + ASCII dump at the supplied memory location.
> + * The converted output is always NUL-terminated.
> + *
> + * E.g.:
> + *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
> + *			linebuf, sizeof(linebuf), true);
> + *
> + * example output buffer:
> + * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
> + *
> + * Return:
> + * The amount of bytes placed in the buffer without terminating NUL. If the
> + * output was truncated, then the return value is the number of bytes
> + * (excluding the terminating NUL) which would have been written to the
> final
> + * string if enough space had been available.
> + */
> +int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int
> groupsize,
> +		       char *linebuf, size_t linebuflen, bool ascii)
> +{
> +	const u8 *ptr = buf;
> +	int ngroups;
> +	u8 ch;
> +	int j, lx = 0;
> +	int ascii_column;
> +	int ret;
> +
> +	if (rowsize != 16 && rowsize != 32)
> +		rowsize = 16;
> +
> +	if (len > rowsize)		/* limit to one line at a time */
> +		len = rowsize;
> +	if (!is_power_of_2(groupsize) || groupsize > 8)
> +		groupsize = 1;
> +	if ((len % groupsize) != 0)	/* no mixed size output */
> +		groupsize = 1;
> +
> +	ngroups = len / groupsize;
> +	ascii_column = rowsize * 2 + rowsize / groupsize + 1;
> +
> +	if (!linebuflen)
> +		goto overflow1;
> +
> +	if (!len)
> +		goto nil;
> +
> +	if (groupsize == 8) {
> +		const u64 *ptr8 = buf;
> +
> +		for (j = 0; j < ngroups; j++) {
> +			ret = snprintf(linebuf + lx, linebuflen - lx,
> +				       "%s%16.16llx", j ? " " : "",
> +				       get_unaligned(ptr8 + j));
> +			if (ret >= linebuflen - lx)
> +				goto overflow1;
> +			lx += ret;
> +		}
> +	} else if (groupsize == 4) {
> +		const u32 *ptr4 = buf;
> +
> +		for (j = 0; j < ngroups; j++) {
> +			ret = snprintf(linebuf + lx, linebuflen - lx,
> +				       "%s%8.8x", j ? " " : "",
> +				       get_unaligned(ptr4 + j));
> +			if (ret >= linebuflen - lx)
> +				goto overflow1;
> +			lx += ret;
> +		}
> +	} else if (groupsize == 2) {
> +		const u16 *ptr2 = buf;
> +
> +		for (j = 0; j < ngroups; j++) {
> +			ret = snprintf(linebuf + lx, linebuflen - lx,
> +				       "%s%4.4x", j ? " " : "",
> +				       get_unaligned(ptr2 + j));
> +			if (ret >= linebuflen - lx)
> +				goto overflow1;
> +			lx += ret;
> +		}
> +	} else {
> +		for (j = 0; j < len; j++) {
> +			if (linebuflen < lx + 2)
> +				goto overflow2;
> +			ch = ptr[j];
> +			linebuf[lx++] = hex_asc_hi(ch);
> +			if (linebuflen < lx + 2)
> +				goto overflow2;
> +			linebuf[lx++] = hex_asc_lo(ch);
> +			if (linebuflen < lx + 2)
> +				goto overflow2;
> +			linebuf[lx++] = ' ';
> +		}
> +		if (j)
> +			lx--;
> +	}
> +	if (!ascii)
> +		goto nil;
> +
> +	while (lx < ascii_column) {
> +		if (linebuflen < lx + 2)
> +			goto overflow2;
> +		linebuf[lx++] = ' ';
> +	}
> +	for (j = 0; j < len; j++) {
> +		if (linebuflen < lx + 2)
> +			goto overflow2;
> +		ch = ptr[j];
> +		linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
> +	}
> +nil:
> +	linebuf[lx] = '\0';
> +	return lx;
> +overflow2:
> +	linebuf[lx++] = '\0';
> +overflow1:
> +	return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
> +}
> +
> +/**
> + * print_hex_dump - print a text hex dump to syslog for a binary blob of
> data
> + * @level: kernel log level (e.g. KERN_DEBUG)
> + * @prefix_str: string to prefix each line with;
> + *  caller supplies trailing spaces for alignment if desired
> + * @prefix_type: controls whether prefix of an offset, address, or none
> + *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS,
> %DUMP_PREFIX_NONE)
> + * @rowsize: number of bytes to print per line; must be 16 or 32
> + * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + * @ascii: include ASCII after the hex output
> + *
> + * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
> + * to the kernel log at the specified kernel log level, with an optional
> + * leading prefix.
> + *
> + * print_hex_dump() works on one "line" of output at a time, i.e.,
> + * 16 or 32 bytes of input data converted to hex + ASCII output.
> + * print_hex_dump() iterates over the entire input @buf, breaking it into
> + * "line size" chunks to format and print.
> + *
> + * E.g.:
> + *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
> + *		    16, 1, frame->data, frame->len, true);
> + *
> + * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
> + * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
> @ABCDEFGHIJKLMNO
> + * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
> + * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c
> pqrstuvwxyz{|}~.
> + */
> +void print_hex_dump(const char *level, const char *prefix_str, int
> prefix_type,
> +		    int rowsize, int groupsize,
> +		    const void *buf, size_t len, bool ascii)
> +{
> +	const u8 *ptr = buf;
> +	int i, linelen, remaining = len;
> +	char linebuf[32 * 3 + 2 + 32 + 1];
> +
> +	if (rowsize != 16 && rowsize != 32)
> +		rowsize = 16;
> +
> +	for (i = 0; i < len; i += rowsize) {
> +		linelen = min(remaining, rowsize);
> +		remaining -= rowsize;
> +
> +		hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
> +				   linebuf, sizeof(linebuf), ascii);
> +
> +		switch (prefix_type) {
> +		case DUMP_PREFIX_ADDRESS:
> +			printf("%s%p: %s\n", prefix_str, ptr + i, linebuf);
> +			break;
> +		case DUMP_PREFIX_OFFSET:
> +			printf("%s%.8x: %s\n", prefix_str, i, linebuf);
> +			break;
> +		default:
> +			printf("%s%s\n", prefix_str, linebuf);
> +			break;
> +		}
> +	}
> +}
> +
> +/**
> + * print_hex_dump_bytes - shorthand form of print_hex_dump() with
> default params
> + * @prefix_str: string to prefix each line with;
> + *  caller supplies trailing spaces for alignment if desired
> + * @prefix_type: controls whether prefix of an offset, address, or none
> + *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS,
> %DUMP_PREFIX_NONE)
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + *
> + * Calls print_hex_dump(), with log level of KERN_DEBUG,
> + * rowsize of 16, groupsize of 1, and ASCII output included.
> + */
> +void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
> +			  const void *buf, size_t len)
> +{
> +	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
> +		       buf, len, true);
> +}
> +
> +#endif /* CONFIG_HEXDUMP */
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 874a295..c0a0aaa 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -271,17 +271,6 @@ static char *string(char *buf, char *end, char *s, int
> field_width,
>  }
> 
>  #ifdef CONFIG_CMD_NET
> -static const char hex_asc[] = "0123456789abcdef";
> -#define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
> -#define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
> -
> -static inline char *pack_hex_byte(char *buf, u8 byte)
> -{
> -	*buf++ = hex_asc_hi(byte);
> -	*buf++ = hex_asc_lo(byte);
> -	return buf;
> -}
> -
>  static char *mac_address_string(char *buf, char *end, u8 *addr, int
> field_width,
>  				int precision, int flags)
>  {
> @@ -291,7 +280,7 @@ static char *mac_address_string(char *buf, char
> *end, u8 *addr, int field_width,
>  	int i;
> 
>  	for (i = 0; i < 6; i++) {
> -		p = pack_hex_byte(p, addr[i]);
> +		p = hex_byte_pack(p, addr[i]);
>  		if (!(flags & SPECIAL) && i != 5)
>  			*p++ = ':';
>  	}
> @@ -310,8 +299,8 @@ static char *ip6_addr_string(char *buf, char *end, u8
> *addr, int field_width,
>  	int i;
> 
>  	for (i = 0; i < 8; i++) {
> -		p = pack_hex_byte(p, addr[2 * i]);
> -		p = pack_hex_byte(p, addr[2 * i + 1]);
> +		p = hex_byte_pack(p, addr[2 * i]);
> +		p = hex_byte_pack(p, addr[2 * i + 1]);
>  		if (!(flags & SPECIAL) && i != 7)
>  			*p++ = ':';
>  	}
> --
> 2.5.5
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels Alexey Brodkin
@ 2016-06-10 19:20   ` Tom Rini
  2016-06-13 12:36     ` Alexey Brodkin
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2016-06-10 19:20 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 10, 2016 at 03:42:30PM +0300, Alexey Brodkin wrote:
> Even currently in U-Boot we don't really use kernel debug levels
> we do have quite a lot of code that was copy-pasted from Linux kernel
> and so contains symbols like KERN_DEBUG and alike.
> 
> We used to just define those symbols which is fine if it is used in
> constructions like:
> ----------------->8--------------
>     printk(KERN_DEBUG "My debug message");
> ----------------->8--------------
> 
> But in other places where the symbol gets passed as a separate
> argument (which we also have but luckily all of them are intself
> dummy stubs in U-Boot) that won't work.
> 
> Now as a preparation to introduction of a real implementation of
> print_hex_dump() we need those symbols to be defined as something real
> so we're taking them as they are from Linux kernel.

Contents are fine but you need to say what version of the kernel you get
it from.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160610/413cb947/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump Alexey Brodkin
  2016-06-10 15:31   ` Langer, Thomas
@ 2016-06-10 19:22   ` Tom Rini
  2016-06-10 20:49     ` Alexey Brodkin
  1 sibling, 1 reply; 15+ messages in thread
From: Tom Rini @ 2016-06-10 19:22 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 10, 2016 at 03:42:31PM +0300, Alexey Brodkin wrote:

> Often during debugging session it's very interesting to see
> what data we were dealing with. For example what we write or read
> to/from memory or peripherals.
> 
> This change introduces functions that allow to dump binary
> data with one simple function invocation like:

Reviewed-by: Tom Rini <trini@konsulko.com>

... except adding to <common.h>.  Do we really need it placed in there?

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160610/f9196952/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 15:31   ` Langer, Thomas
@ 2016-06-10 19:37     ` Tom Rini
  2016-06-10 20:51       ` Alexey Brodkin
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2016-06-10 19:37 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 10, 2016 at 03:31:30PM +0000, Langer, Thomas wrote:

> Hello Alexey,
> 
> This feature is already available in u-boot, please look for 'print_buffer'.

... make this a candidate for moving over to the linux kernel way?

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160610/4bf07231/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 19:22   ` Tom Rini
@ 2016-06-10 20:49     ` Alexey Brodkin
  0 siblings, 0 replies; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-10 20:49 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Fri, 2016-06-10 at 15:22 -0400, Tom Rini wrote:
> On Fri, Jun 10, 2016 at 03:42:31PM +0300, Alexey Brodkin wrote:
> 
> > 
> > Often during debugging session it's very interesting to see
> > what data we were dealing with. For example what we write or read
> > to/from memory or peripherals.
> > 
> > This change introduces functions that allow to dump binary
> > data with one simple function invocation like:
> Reviewed-by: Tom Rini <trini@konsulko.com>
> 
> ... except adding to <common.h>.??Do we really need it placed in there?
> 

Rationale behind it was to keep a minimal amount of changes.
I mean those mentioned existing "users" of hexdump will require
explicit mention of that new header which I wanted to escape.

Still I may agree with proposal to remove hexdump.h from common.h...
if we're going to accept this patch at all [in any form]...

-Alexey

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 19:37     ` Tom Rini
@ 2016-06-10 20:51       ` Alexey Brodkin
  2016-06-10 21:39         ` Tom Rini
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-10 20:51 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Fri, 2016-06-10 at 15:37 -0400, Tom Rini wrote:
> On Fri, Jun 10, 2016 at 03:31:30PM +0000, Langer, Thomas wrote:
> 
> > 
> > Hello Alexey,
> > 
> > This feature is already available in u-boot, please look for 'print_buffer'.
>
> ... make this a candidate for moving over to the linux kernel way?

Could you please elaborate here a little bit?
I didn't quite understood what do you propose really...
Switch in U-Boot to kernel's hexdump or send patches with U-Boot's
print_buffer to LKML?

-Alexey

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 20:51       ` Alexey Brodkin
@ 2016-06-10 21:39         ` Tom Rini
  2016-06-10 21:58           ` Алексей Бродкин
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2016-06-10 21:39 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 10, 2016 at 11:51:20PM +0300, Alexey Brodkin wrote:
> Hi Tom,
> 
> On Fri, 2016-06-10 at 15:37 -0400, Tom Rini wrote:
> > On Fri, Jun 10, 2016 at 03:31:30PM +0000, Langer, Thomas wrote:
> > 
> > > 
> > > Hello Alexey,
> > > 
> > > This feature is already available in u-boot, please look for 'print_buffer'.
> >
> > ... make this a candidate for moving over to the linux kernel way?
> 
> Could you please elaborate here a little bit?
> I didn't quite understood what do you propose really...
> Switch in U-Boot to kernel's hexdump or send patches with U-Boot's
> print_buffer to LKML?

OK, to be clear and answer both emails, we should:
a) Only add the new header when calling the new function
b) Add further parts to the series to convert current users of
print_buffer to these functions instead to reduce the mental changes one
makes when doing / reading U-Boot code vs Linux Kernel code.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160610/7e35879e/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 21:39         ` Tom Rini
@ 2016-06-10 21:58           ` Алексей Бродкин
  2016-06-10 22:18             ` Tom Rini
  0 siblings, 1 reply; 15+ messages in thread
From: Алексей Бродкин @ 2016-06-10 21:58 UTC (permalink / raw)
  To: u-boot

Hi Tom,

2016-06-11 0:39 GMT+03:00 Tom Rini <trini@konsulko.com>:
> On Fri, Jun 10, 2016 at 11:51:20PM +0300, Alexey Brodkin wrote:
>> Hi Tom,
>>
>> On Fri, 2016-06-10 at 15:37 -0400, Tom Rini wrote:
>> > On Fri, Jun 10, 2016 at 03:31:30PM +0000, Langer, Thomas wrote:
>> >
>> > >
>> > > Hello Alexey,
>> > >
>> > > This feature is already available in u-boot, please look for 'print_buffer'.
>> >
>> > ... make this a candidate for moving over to the linux kernel way?
>>
>> Could you please elaborate here a little bit?
>> I didn't quite understood what do you propose really...
>> Switch in U-Boot to kernel's hexdump or send patches with U-Boot's
>> print_buffer to LKML?
>
> OK, to be clear and answer both emails, we should:

I'm sorry but again I cannot understand your proposal completely :)

> a) Only add the new header when calling the new function

What do you mean here?

> b) Add further parts to the series to convert current users of
> print_buffer to these functions instead to reduce the mental changes one
> makes when doing / reading U-Boot code vs Linux Kernel code.

Agree, that definitely make sense.
But note there's a subtle issue in there. Kernel's implementation of
print_hex_dump() assumes
debug level which in case of Linux kernel makes perfect sense. But for
U-Boot it is barely usable. So we may keep prototype of
print_hex_dump() as it is just ignorihg KERN_XXX stuff
or have U-Boot's own version with the first argument removed. But in
latter case we'll need to
update those "current users" of print_hex_dump.

Any thoughts?

-Alexey

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
  2016-06-10 21:58           ` Алексей Бродкин
@ 2016-06-10 22:18             ` Tom Rini
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Rini @ 2016-06-10 22:18 UTC (permalink / raw)
  To: u-boot

On Sat, Jun 11, 2016 at 12:58:14AM +0300, ??????? ??????? wrote:
> Hi Tom,
> 
> 2016-06-11 0:39 GMT+03:00 Tom Rini <trini@konsulko.com>:
> > On Fri, Jun 10, 2016 at 11:51:20PM +0300, Alexey Brodkin wrote:
> >> Hi Tom,
> >>
> >> On Fri, 2016-06-10 at 15:37 -0400, Tom Rini wrote:
> >> > On Fri, Jun 10, 2016 at 03:31:30PM +0000, Langer, Thomas wrote:
> >> >
> >> > >
> >> > > Hello Alexey,
> >> > >
> >> > > This feature is already available in u-boot, please look for 'print_buffer'.
> >> >
> >> > ... make this a candidate for moving over to the linux kernel way?
> >>
> >> Could you please elaborate here a little bit?
> >> I didn't quite understood what do you propose really...
> >> Switch in U-Boot to kernel's hexdump or send patches with U-Boot's
> >> print_buffer to LKML?
> >
> > OK, to be clear and answer both emails, we should:
> 
> I'm sorry but again I cannot understand your proposal completely :)
> 
> > a) Only add the new header when calling the new function
> 
> What do you mean here?

No <hexdump.h> in <common.h> and only add <hexdump.h> when the C file is
calling a related function.

> > b) Add further parts to the series to convert current users of
> > print_buffer to these functions instead to reduce the mental changes one
> > makes when doing / reading U-Boot code vs Linux Kernel code.
> 
> Agree, that definitely make sense.
> But note there's a subtle issue in there. Kernel's implementation of
> print_hex_dump() assumes
> debug level which in case of Linux kernel makes perfect sense. But for
> U-Boot it is barely usable. So we may keep prototype of
> print_hex_dump() as it is just ignorihg KERN_XXX stuff
> or have U-Boot's own version with the first argument removed. But in
> latter case we'll need to
> update those "current users" of print_hex_dump.
> 
> Any thoughts?

Continue to ignore the level as you've done and then yes, we'll have to
make sure to carefully convert existing callers.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160610/210b8b29/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels
  2016-06-10 19:20   ` Tom Rini
@ 2016-06-13 12:36     ` Alexey Brodkin
  2016-06-13 14:13       ` Tom Rini
  0 siblings, 1 reply; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-13 12:36 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Fri, 2016-06-10 at 15:20 -0400, Tom Rini wrote:
> On Fri, Jun 10, 2016 at 03:42:30PM +0300, Alexey Brodkin wrote:
> > 
> > Even currently in U-Boot we don't really use kernel debug levels
> > we do have quite a lot of code that was copy-pasted from Linux kernel
> > and so contains symbols like KERN_DEBUG and alike.
> > 
> > We used to just define those symbols which is fine if it is used in
> > constructions like:
> > ----------------->8--------------
> > ????printk(KERN_DEBUG "My debug message");
> > ----------------->8--------------
> > 
> > But in other places where the symbol gets passed as a separate
> > argument (which we also have but luckily all of them are intself
> > dummy stubs in U-Boot) that won't work.
> > 
> > Now as a preparation to introduction of a real implementation of
> > print_hex_dump() we need those symbols to be defined as something real
> > so we're taking them as they are from Linux kernel.
>
> Contents are fine but you need to say what version of the kernel you get
> it from.

This is taken from 4.7-rc2.

Given print_hex_dump() requires rework in a sense that we want to replace
existing print_buffer() with it maybe we apply this patch because it has
no dependencies on anything else?

If you want I may resend it with added info about kernel version used for
copy, or alternatively you may fixup it on patch application.

-Alexey

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels
  2016-06-13 12:36     ` Alexey Brodkin
@ 2016-06-13 14:13       ` Tom Rini
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Rini @ 2016-06-13 14:13 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 13, 2016 at 12:36:04PM +0000, Alexey Brodkin wrote:
> Hi Tom,
> 
> On Fri, 2016-06-10 at 15:20 -0400, Tom Rini wrote:
> > On Fri, Jun 10, 2016 at 03:42:30PM +0300, Alexey Brodkin wrote:
> > > 
> > > Even currently in U-Boot we don't really use kernel debug levels
> > > we do have quite a lot of code that was copy-pasted from Linux kernel
> > > and so contains symbols like KERN_DEBUG and alike.
> > > 
> > > We used to just define those symbols which is fine if it is used in
> > > constructions like:
> > > ----------------->8--------------
> > > ????printk(KERN_DEBUG "My debug message");
> > > ----------------->8--------------
> > > 
> > > But in other places where the symbol gets passed as a separate
> > > argument (which we also have but luckily all of them are intself
> > > dummy stubs in U-Boot) that won't work.
> > > 
> > > Now as a preparation to introduction of a real implementation of
> > > print_hex_dump() we need those symbols to be defined as something real
> > > so we're taking them as they are from Linux kernel.
> >
> > Contents are fine but you need to say what version of the kernel you get
> > it from.
> 
> This is taken from 4.7-rc2.
> 
> Given print_hex_dump() requires rework in a sense that we want to replace
> existing print_buffer() with it maybe we apply this patch because it has
> no dependencies on anything else?
> 
> If you want I may resend it with added info about kernel version used for
> copy, or alternatively you may fixup it on patch application.

Please just update the commit message here for the next iteration on
this patch set, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160613/d6ad1ea3/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
@ 2016-06-10 15:39 Alexey Brodkin
  0 siblings, 0 replies; 15+ messages in thread
From: Alexey Brodkin @ 2016-06-10 15:39 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

I was pretty sure I saw it before but today having no idea how that thing might be called I grepped for something like "dump", "buffer" etc but within tons of unrelated things I failed to find that "print_buffer"... such a shame...

-Alexey

10 ???? 2016 ?. 18:32 ???????????? "Langer, Thomas" <thomas.langer@intel.com> ???????:
Hello Alexey,

This feature is already available in u-boot, please look for 'print_buffer'.

Best regards,
Thomas

> -----Original Message-----
> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Alexey
> Brodkin
> Sent: Friday, June 10, 2016 2:43 PM
> To: u-boot at lists.denx.de
> Cc: Tom Rini <trini@konsulko.com>; Alexey Brodkin
> <Alexey.Brodkin@synopsys.com>
> Subject: [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump
>
> Often during debugging session it's very interesting to see
> what data we were dealing with. For example what we write or read
> to/from memory or peripherals.
>
> This change introduces functions that allow to dump binary
> data with one simple function invocation like:
> ------------------->8----------------
> print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
> ------------------->8----------------
>
> which gives us the following:
> ------------------->8----------------
> 00000000: f2 b7 c9 88 62 61 75 64 72 61 74 65 3d 31 31 35  ....baudrate=115
> 00000010: 32 30 30 00 62 6f 6f 74 61 72 67 73 3d 63 6f 6e  200.bootargs=con
> 00000020: 73 6f 6c 65 3d 74 74 79 53 33 2c 31 31 35 32 30  sole=ttyS3,11520
> 00000030: 30 6e 38 00 62 6f 6f 74 64 65 6c 61 79 3d 33 00  0n8.bootdelay=3.
> 00000040: 62 6f 6f 74 66 69 6c 65 3d 75 49 6d 61 67 65 00  bootfile=uImage.
> 00000050: 66 64 74 63 6f 6e 74 72 6f 6c 61 64 64 72 3d 39  fdtcontroladdr=9
> 00000060: 66 66 62 31 62 61 30 00 6c 6f 61 64 61 64 64 72  ffb1ba0.loadaddr
> 00000070: 3d 30 78 38 32 30 30 30 30 30 30 00 73 74 64 65
> =0x82000000.stde
> 00000080: 72 72 3d 73 65 72 69 61 6c 30 40 65 30 30 32 32
> rr=serial0 at e0022
> 00000090: 30 30 30 00 73 74 64 69 6e 3d 73 65 72 69 61 6c  000.stdin=serial
> 000000a0: 30 40 65 30 30 32 32 30 30 30 00 73 74 64 6f 75
> 0 at e0022000.stdou
> 000000b0: 74 3d 73 65 72 69 61 6c 30 40 65 30 30 32 32 30
> t=serial0 at e00220
> 000000c0: 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00..............
> ...
> ------------------->8----------------
>
> Source of hexdump.c was copied from Linux kernel v4.7-rc2.
>
> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> Reviewed-by: Stefan Roese <sr@denx.de>
> Cc: Tom Rini <trini@konsulko.com>
>
> ---
>
> Changes v1 -> v2:
>  * Move hexdump definitions to a separate header.
>  * Move helper funcions to the header so they might be used even if
>    CONFIG_HEXDUMP is not enabled and if not used they will not occupy
>    extra bytes of memory being "static inline" ones.
>  * While at it replace its own hex_asc[], hex_asc_{lo|hi}() and
>    pack_hex_byte() in lib/vsprintf.c with generic ones from hexdump.
>  * In print_hex_dump() revert back first parametr for debug level,
>    otherwise existing users of the function will be broken.
>
>  include/common.h       |   1 +
>  include/hexdump.h      | 108 +++++++++++++++++++++++
>  include/linux/compat.h |   1 -
>  lib/Kconfig            |   5 ++
>  lib/Makefile           |   1 +
>  lib/hexdump.c          | 233
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/vsprintf.c         |  17 +---
>  7 files changed, 351 insertions(+), 15 deletions(-)
>  create mode 100644 include/hexdump.h
>  create mode 100644 lib/hexdump.c
>
> diff --git a/include/common.h b/include/common.h
> index f9f4605..51a438c 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -23,6 +23,7 @@ typedef volatile unsigned char      vu_char;
>  #include <linux/stringify.h>
>  #include <asm/ptrace.h>
>  #include <stdarg.h>
> +#include <hexdump.h>
>  #include <linux/kernel.h>
>  #if defined(CONFIG_PCI) && defined(CONFIG_4xx)
>  #include <pci.h>
> diff --git a/include/hexdump.h b/include/hexdump.h
> new file mode 100644
> index 0000000..de2e565
> --- /dev/null
> +++ b/include/hexdump.h
> @@ -0,0 +1,108 @@
> +/*
> + * Copyright (C) 2016 Synopsys, Inc. All rights reserved.
> + *
> + * SPDX-License-Identifier:  GPL-2.0+
> + */
> +
> +#ifndef HEXDUMP_H
> +#define HEXDUMP_H
> +
> +#include <linux/ctype.h>
> +
> +enum {
> +     DUMP_PREFIX_NONE,
> +     DUMP_PREFIX_ADDRESS,
> +     DUMP_PREFIX_OFFSET
> +};
> +
> +extern const char hex_asc[];
> +#define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]
> +#define hex_asc_hi(x)        hex_asc[((x) & 0xf0) >> 4]
> +
> +static inline char *hex_byte_pack(char *buf, u8 byte)
> +{
> +     *buf++ = hex_asc_hi(byte);
> +     *buf++ = hex_asc_lo(byte);
> +     return buf;
> +}
> +
> +/**
> + * hex_to_bin - convert a hex digit to its real value
> + * @ch: ascii character represents hex digit
> + *
> + * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
> + * input.
> + */
> +static inline int hex_to_bin(char ch)
> +{
> +     if ((ch >= '0') && (ch <= '9'))
> +             return ch - '0';
> +     ch = tolower(ch);
> +     if ((ch >= 'a') && (ch <= 'f'))
> +             return ch - 'a' + 10;
> +     return -1;
> +}
> +
> +/**
> + * hex2bin - convert an ascii hexadecimal string to its binary representation
> + * @dst: binary result
> + * @src: ascii hexadecimal string
> + * @count: result length
> + *
> + * Return 0 on success, -1 in case of bad input.
> + */
> +static inline int hex2bin(u8 *dst, const char *src, size_t count)
> +{
> +     while (count--) {
> +             int hi = hex_to_bin(*src++);
> +             int lo = hex_to_bin(*src++);
> +
> +             if ((hi < 0) || (lo < 0))
> +                     return -1;
> +
> +             *dst++ = (hi << 4) | lo;
> +     }
> +     return 0;
> +}
> +
> +/**
> + * bin2hex - convert binary data to an ascii hexadecimal string
> + * @dst: ascii hexadecimal result
> + * @src: binary data
> + * @count: binary data length
> + */
> +static inline char *bin2hex(char *dst, const void *src, size_t count)
> +{
> +     const unsigned char *_src = src;
> +
> +     while (count--)
> +             dst = hex_byte_pack(dst, *_src++);
> +     return dst;
> +}
> +
> +
> +#ifdef CONFIG_HEXDUMP
> +int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int
> groupsize,
> +                    char *linebuf, size_t linebuflen, bool ascii);
> +void print_hex_dump(const char *level, const char *prefix_str, int
> prefix_type,
> +                 int rowsize, int groupsize, const void *buf, size_t len,
> +                 bool ascii);
> +void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
> +                       const void *buf, size_t len);
> +#else /* !CONFIG_HEXDUMP */
> +/*
> + * Some code in U-Boot copy-pasted from Linux kernel uses both
> + * functions below so to keep stuff compilable we keep these stubs here.
> + */
> +static inline void print_hex_dump(const char *level, const char *prefix_str,
> +                               int prefix_type, int rowsize, int groupsize,
> +                               const void *buf, size_t len, bool ascii)
> +{
> +}
> +static inline void print_hex_dump_bytes(const char *prefix_str, int
> prefix_type,
> +                                     const void *buf, size_t len)
> +{
> +}
> +#endif /* CONFIG_HEXDUMP */
> +
> +#endif /* HEXDUMP_H */
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index 0ce7d65..074a85e 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -193,7 +193,6 @@ typedef unsigned long blkcnt_t;
>  #define init_waitqueue_head(...)     do { } while (0)
>  #define wait_event_interruptible(...)        0
>  #define wake_up_interruptible(...)   do { } while (0)
> -#define print_hex_dump(...)          do { } while (0)
>  #define dump_stack(...)                      do { } while (0)
>
>  #define task_pid_nr(x)                       0
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 2b97c2b..a563b5e 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -128,6 +128,11 @@ config ERRNO_STR
>          - if errno is null or positive number - a pointer to "Success" message
>          - if errno is negative - a pointer to errno related message
>
> +config HEXDUMP
> +     bool "Enable hexdump"
> +     help
> +       This enables functions for printing dumps of binary data.
> +
>  config OF_LIBFDT
>        bool "Enable the FDT library"
>        default y if OF_CONTROL
> diff --git a/lib/Makefile b/lib/Makefile
> index 02dfa29..1bf7c37 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -76,6 +76,7 @@ obj-y += membuff.o
>  obj-$(CONFIG_REGEX) += slre.o
>  obj-y += string.o
>  obj-y += time.o
> +obj-y += hexdump.o
>  obj-$(CONFIG_TRACE) += trace.o
>  obj-$(CONFIG_LIB_UUID) += uuid.o
>  obj-$(CONFIG_LIB_RAND) += rand.o
> diff --git a/lib/hexdump.c b/lib/hexdump.c
> new file mode 100644
> index 0000000..ffee5ce
> --- /dev/null
> +++ b/lib/hexdump.c
> @@ -0,0 +1,233 @@
> +/*
> + * lib/hexdump.c
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation. See README and COPYING
> for
> + * more details.
> + */
> +
> +#include <common.h>
> +#include <linux/ctype.h>
> +#include <linux/compat.h>
> +#include <linux/log2.h>
> +#include <asm/unaligned.h>
> +
> +const char hex_asc[] = "0123456789abcdef";
> +const char hex_asc_upper[] = "0123456789ABCDEF";
> +
> +#ifdef CONFIG_HEXDUMP
> +/**
> + * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + * @rowsize: number of bytes to print per line; must be 16 or 32
> + * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
> + * @linebuf: where to put the converted data
> + * @linebuflen: total size of @linebuf, including space for terminating NUL
> + * @ascii: include ASCII after the hex output
> + *
> + * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
> + * 16 or 32 bytes of input data converted to hex + ASCII output.
> + *
> + * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
> + * to a hex + ASCII dump at the supplied memory location.
> + * The converted output is always NUL-terminated.
> + *
> + * E.g.:
> + *   hex_dump_to_buffer(frame->data, frame->len, 16, 1,
> + *                   linebuf, sizeof(linebuf), true);
> + *
> + * example output buffer:
> + * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO
> + *
> + * Return:
> + * The amount of bytes placed in the buffer without terminating NUL. If the
> + * output was truncated, then the return value is the number of bytes
> + * (excluding the terminating NUL) which would have been written to the
> final
> + * string if enough space had been available.
> + */
> +int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int
> groupsize,
> +                    char *linebuf, size_t linebuflen, bool ascii)
> +{
> +     const u8 *ptr = buf;
> +     int ngroups;
> +     u8 ch;
> +     int j, lx = 0;
> +     int ascii_column;
> +     int ret;
> +
> +     if (rowsize != 16 && rowsize != 32)
> +             rowsize = 16;
> +
> +     if (len > rowsize)              /* limit to one line at a time */
> +             len = rowsize;
> +     if (!is_power_of_2(groupsize) || groupsize > 8)
> +             groupsize = 1;
> +     if ((len % groupsize) != 0)     /* no mixed size output */
> +             groupsize = 1;
> +
> +     ngroups = len / groupsize;
> +     ascii_column = rowsize * 2 + rowsize / groupsize + 1;
> +
> +     if (!linebuflen)
> +             goto overflow1;
> +
> +     if (!len)
> +             goto nil;
> +
> +     if (groupsize == 8) {
> +             const u64 *ptr8 = buf;
> +
> +             for (j = 0; j < ngroups; j++) {
> +                     ret = snprintf(linebuf + lx, linebuflen - lx,
> +                                    "%s%16.16llx", j ? " " : "",
> +                                    get_unaligned(ptr8 + j));
> +                     if (ret >= linebuflen - lx)
> +                             goto overflow1;
> +                     lx += ret;
> +             }
> +     } else if (groupsize == 4) {
> +             const u32 *ptr4 = buf;
> +
> +             for (j = 0; j < ngroups; j++) {
> +                     ret = snprintf(linebuf + lx, linebuflen - lx,
> +                                    "%s%8.8x", j ? " " : "",
> +                                    get_unaligned(ptr4 + j));
> +                     if (ret >= linebuflen - lx)
> +                             goto overflow1;
> +                     lx += ret;
> +             }
> +     } else if (groupsize == 2) {
> +             const u16 *ptr2 = buf;
> +
> +             for (j = 0; j < ngroups; j++) {
> +                     ret = snprintf(linebuf + lx, linebuflen - lx,
> +                                    "%s%4.4x", j ? " " : "",
> +                                    get_unaligned(ptr2 + j));
> +                     if (ret >= linebuflen - lx)
> +                             goto overflow1;
> +                     lx += ret;
> +             }
> +     } else {
> +             for (j = 0; j < len; j++) {
> +                     if (linebuflen < lx + 2)
> +                             goto overflow2;
> +                     ch = ptr[j];
> +                     linebuf[lx++] = hex_asc_hi(ch);
> +                     if (linebuflen < lx + 2)
> +                             goto overflow2;
> +                     linebuf[lx++] = hex_asc_lo(ch);
> +                     if (linebuflen < lx + 2)
> +                             goto overflow2;
> +                     linebuf[lx++] = ' ';
> +             }
> +             if (j)
> +                     lx--;
> +     }
> +     if (!ascii)
> +             goto nil;
> +
> +     while (lx < ascii_column) {
> +             if (linebuflen < lx + 2)
> +                     goto overflow2;
> +             linebuf[lx++] = ' ';
> +     }
> +     for (j = 0; j < len; j++) {
> +             if (linebuflen < lx + 2)
> +                     goto overflow2;
> +             ch = ptr[j];
> +             linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.';
> +     }
> +nil:
> +     linebuf[lx] = '\0';
> +     return lx;
> +overflow2:
> +     linebuf[lx++] = '\0';
> +overflow1:
> +     return ascii ? ascii_column + len : (groupsize * 2 + 1) * ngroups - 1;
> +}
> +
> +/**
> + * print_hex_dump - print a text hex dump to syslog for a binary blob of
> data
> + * @level: kernel log level (e.g. KERN_DEBUG)
> + * @prefix_str: string to prefix each line with;
> + *  caller supplies trailing spaces for alignment if desired
> + * @prefix_type: controls whether prefix of an offset, address, or none
> + *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS,
> %DUMP_PREFIX_NONE)
> + * @rowsize: number of bytes to print per line; must be 16 or 32
> + * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + * @ascii: include ASCII after the hex output
> + *
> + * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
> + * to the kernel log at the specified kernel log level, with an optional
> + * leading prefix.
> + *
> + * print_hex_dump() works on one "line" of output at a time, i.e.,
> + * 16 or 32 bytes of input data converted to hex + ASCII output.
> + * print_hex_dump() iterates over the entire input @buf, breaking it into
> + * "line size" chunks to format and print.
> + *
> + * E.g.:
> + *   print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
> + *               16, 1, frame->data, frame->len, true);
> + *
> + * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
> + * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
> @ABCDEFGHIJKLMNO
> + * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
> + * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c
> pqrstuvwxyz{|}~.
> + */
> +void print_hex_dump(const char *level, const char *prefix_str, int
> prefix_type,
> +                 int rowsize, int groupsize,
> +                 const void *buf, size_t len, bool ascii)
> +{
> +     const u8 *ptr = buf;
> +     int i, linelen, remaining = len;
> +     char linebuf[32 * 3 + 2 + 32 + 1];
> +
> +     if (rowsize != 16 && rowsize != 32)
> +             rowsize = 16;
> +
> +     for (i = 0; i < len; i += rowsize) {
> +             linelen = min(remaining, rowsize);
> +             remaining -= rowsize;
> +
> +             hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
> +                                linebuf, sizeof(linebuf), ascii);
> +
> +             switch (prefix_type) {
> +             case DUMP_PREFIX_ADDRESS:
> +                     printf("%s%p: %s\n", prefix_str, ptr + i, linebuf);
> +                     break;
> +             case DUMP_PREFIX_OFFSET:
> +                     printf("%s%.8x: %s\n", prefix_str, i, linebuf);
> +                     break;
> +             default:
> +                     printf("%s%s\n", prefix_str, linebuf);
> +                     break;
> +             }
> +     }
> +}
> +
> +/**
> + * print_hex_dump_bytes - shorthand form of print_hex_dump() with
> default params
> + * @prefix_str: string to prefix each line with;
> + *  caller supplies trailing spaces for alignment if desired
> + * @prefix_type: controls whether prefix of an offset, address, or none
> + *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS,
> %DUMP_PREFIX_NONE)
> + * @buf: data blob to dump
> + * @len: number of bytes in the @buf
> + *
> + * Calls print_hex_dump(), with log level of KERN_DEBUG,
> + * rowsize of 16, groupsize of 1, and ASCII output included.
> + */
> +void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
> +                       const void *buf, size_t len)
> +{
> +     print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
> +                    buf, len, true);
> +}
> +
> +#endif /* CONFIG_HEXDUMP */
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 874a295..c0a0aaa 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -271,17 +271,6 @@ static char *string(char *buf, char *end, char *s, int
> field_width,
>  }
>
>  #ifdef CONFIG_CMD_NET
> -static const char hex_asc[] = "0123456789abcdef";
> -#define hex_asc_lo(x)        hex_asc[((x) & 0x0f)]
> -#define hex_asc_hi(x)        hex_asc[((x) & 0xf0) >> 4]
> -
> -static inline char *pack_hex_byte(char *buf, u8 byte)
> -{
> -     *buf++ = hex_asc_hi(byte);
> -     *buf++ = hex_asc_lo(byte);
> -     return buf;
> -}
> -
>  static char *mac_address_string(char *buf, char *end, u8 *addr, int
> field_width,
>                                int precision, int flags)
>  {
> @@ -291,7 +280,7 @@ static char *mac_address_string(char *buf, char
> *end, u8 *addr, int field_width,
>        int i;
>
>        for (i = 0; i < 6; i++) {
> -             p = pack_hex_byte(p, addr[i]);
> +             p = hex_byte_pack(p, addr[i]);
>                if (!(flags & SPECIAL) && i != 5)
>                        *p++ = ':';
>        }
> @@ -310,8 +299,8 @@ static char *ip6_addr_string(char *buf, char *end, u8
> *addr, int field_width,
>        int i;
>
>        for (i = 0; i < 8; i++) {
> -             p = pack_hex_byte(p, addr[2 * i]);
> -             p = pack_hex_byte(p, addr[2 * i + 1]);
> +             p = hex_byte_pack(p, addr[2 * i]);
> +             p = hex_byte_pack(p, addr[2 * i + 1]);
>                if (!(flags & SPECIAL) && i != 7)
>                        *p++ = ':';
>        }
> --
> 2.5.5
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-06-13 14:13 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-10 12:42 [U-Boot] [PATCH RESEND 0/2 v2] Introduce hexdump Alexey Brodkin
2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 1/2 v2] linux-compat: Use original kern_levels.h for kernel debug levels Alexey Brodkin
2016-06-10 19:20   ` Tom Rini
2016-06-13 12:36     ` Alexey Brodkin
2016-06-13 14:13       ` Tom Rini
2016-06-10 12:42 ` [U-Boot] [PATCH RESEND 2/2 v2] lib: Add hexdump Alexey Brodkin
2016-06-10 15:31   ` Langer, Thomas
2016-06-10 19:37     ` Tom Rini
2016-06-10 20:51       ` Alexey Brodkin
2016-06-10 21:39         ` Tom Rini
2016-06-10 21:58           ` Алексей Бродкин
2016-06-10 22:18             ` Tom Rini
2016-06-10 19:22   ` Tom Rini
2016-06-10 20:49     ` Alexey Brodkin
2016-06-10 15:39 Alexey Brodkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.