Re: [PATCH v4 5/7] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
On Mon, 2019-06-24 at 22:37 -0700, Joe Perches wrote: > On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > With the wider display format, it can become hard to identify how > > many > > bytes into the line you are looking at. > > > > The patch adds new flags to hex_dump_to_buffer() and > > print_hex_dump() to > > print vertical lines to separate every N groups of bytes. > > > > eg. > > buf:: 454d414e 43415053|4e495f45 > > 00584544 NAMESPAC|E_INDEX. > > buf:0010: 0000 0002| > > | > > > > Signed-off-by: Alastair D'Silva > > --- > > include/linux/printk.h | 3 +++ > > lib/hexdump.c | 59 > > -- > > 2 files changed, 54 insertions(+), 8 deletions(-) > > > > diff --git a/include/linux/printk.h b/include/linux/printk.h > [] > > @@ -485,6 +485,9 @@ enum { > > > > #define HEXDUMP_ASCII BIT(0) > > #define HEXDUMP_SUPPRESS_REPEATED BIT(1) > > +#define HEXDUMP_2_GRP_LINESBIT(2) > > +#define HEXDUMP_4_GRP_LINESBIT(3) > > +#define HEXDUMP_8_GRP_LINESBIT(4) > > These aren't really bits as only one value should be set > as 8 overrides 4 and 4 overrides 2. This should be the other way around, as we should be emitting alternate seperators based on the smallest grouping (2 implies 4 and 8, and 4 implies 8). I'll fix the logic. I can't come up with a better way to represent these without making the API more complex, if you have a suggestion, I'm happy to hear it. > > I would also expect this to be a value of 2 in your above > example, rather than 8. It's described as groups not bytes. > > The example is showing a what would normally be a space ' ' > separator as a vertical bar '|' every 2nd grouping. > The above example shows a group size of 4 bytes, and HEXDUMP_2_GRP_LINES set, with 2 groups being 8 bytes. I'll make that clearer in the commit message. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
On Mon, 2019-06-24 at 22:01 -0700, Joe Perches wrote: > On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > In order to support additional features, rename hex_dump_to_buffer > > to > > hex_dump_to_buffer_ext, and replace the ascii bool parameter with > > flags. > [] > > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c > > b/drivers/gpu/drm/i915/intel_engine_cs.c > [] > > @@ -1338,9 +1338,8 @@ static void hexdump(struct drm_printer *m, > > const void *buf, size_t len) > > } > > > > WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, > > - rowsize, sizeof(u32), > > - line, sizeof(line), > > - false) >= > > sizeof(line)); > > + rowsize, sizeof(u32), > > line, > > + sizeof(line)) >= > > sizeof(line)); > > Huh? Why do this? The ascii parameter was removed from the simple API as per Jani's suggestion. The remainder was reformatted to avoid exceeding the line length limits. > > > diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c > > b/drivers/isdn/hardware/mISDN/mISDNisar.c > [] > > @@ -70,8 +70,9 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, > > u8 len, u8 *msg) > > int l = 0; > > > > while (l < (int)len) { > > - hex_dump_to_buffer(msg + l, len - l, > > 32, 1, > > - isar->log, 256, 1); > > + hex_dump_to_buffer_ext(msg + l, len - > > l, 32, 1, > > + isar->log, 256, > > + HEXDUMP_ASCII); > > Again, why do any of these? > > The point of the wrapper is to avoid changing these. Jani made a pretty good point that about half the callers didn't want an ASCII dump, and presenting a simplified API makes sense. I would actually put forward that we consider dropping rowsize from the simplified API too, as most callers use 32, and those that use 16 would probably be OK with 32. Your proposal, on the other hand, only makes sense if there were many callers, and even so, not in the form that you presented, since that result in a mix of booleans & bitfields that you were critical of. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 0/7] Hexdump Enhancements
On Mon, 2019-06-24 at 22:01 -0700, Joe Perches wrote: > On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > Apologies for the large CC list, it's a heads up for those > > responsible > > for subsystems where a prototype change in generic code causes a > > change > > in those subsystems. > [] > > The default behaviour of hexdump is unchanged, however, the > > prototype > > for hex_dump_to_buffer() has changed, and print_hex_dump() has been > > renamed to print_hex_dump_ext(), with a wrapper replacing it for > > compatibility with existing code, which would have been too > > invasive to > > change. > > I believe this cover letter is misleading. > > The point of the wrapper is to avoid unnecessary changes > in existing > code. > > The wrapper is for print_hex_dump(), which has many callers. The changes to existing code are for hex_dump_to_buffer(), which is called in relatively few places. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
On Mon, 2019-06-24 at 22:19 -0700, Joe Perches wrote: > On Tue, 2019-06-25 at 15:06 +1000, Alastair D'Silva wrote: > > The change actions Jani's suggestion: > > https://lkml.org/lkml/2019/6/20/343 > > I suggest not changing any of the existing uses of > hex_dump_to_buffer and only use hex_dump_to_buffer_ext > when necessary for your extended use cases. > > I disagree, adding a wrapper for the benefit of avoiding touching a handful of call sites that are easily amended would be adding technical debt. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v4 6/7] lib/hexdump.c: Allow multiple groups to be separated by spaces
From: Alastair D'Silva Similar to the previous patch, this patch separates groups by 2 spaces for the hex fields, and 1 space for the ASCII field. eg. buf:: 454d414e 43415053 4e495f45 00584544 NAMESPAC E_INDEX. buf:0010: 0002 Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 ++ lib/hexdump.c | 65 +++--- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index ae80d7af82ab..1d082291facf 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -488,6 +488,9 @@ enum { #define HEXDUMP_2_GRP_LINESBIT(2) #define HEXDUMP_4_GRP_LINESBIT(3) #define HEXDUMP_8_GRP_LINESBIT(4) +#define HEXDUMP_2_GRP_SPACES BIT(5) +#define HEXDUMP_4_GRP_SPACES BIT(6) +#define HEXDUMP_8_GRP_SPACES BIT(7) extern int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index 4dcf759fe048..e09e3cf8e595 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -91,9 +91,37 @@ static const char *group_separator(int group, u64 flags) if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2)) return "|"; + if ((flags & HEXDUMP_8_GRP_SPACES) && !((group) % 8)) + return " "; + + if ((flags & HEXDUMP_4_GRP_SPACES) && !((group) % 4)) + return " "; + + if ((flags & HEXDUMP_2_GRP_SPACES) && !((group) % 2)) + return " "; + return " "; } +static void separator_parameters(u64 flags, int groupsize, int *sep_chars, +char *sep) +{ + if (flags & (HEXDUMP_2_GRP_LINES | HEXDUMP_2_GRP_SPACES)) + *sep_chars = groupsize * 2; + if (flags & (HEXDUMP_4_GRP_LINES | HEXDUMP_4_GRP_SPACES)) + *sep_chars = groupsize * 4; + if (flags & (HEXDUMP_8_GRP_LINES | HEXDUMP_8_GRP_SPACES)) + *sep_chars = groupsize * 8; + + if (flags & (HEXDUMP_2_GRP_LINES | HEXDUMP_4_GRP_LINES | + HEXDUMP_8_GRP_LINES)) + *sep = '|'; + + if (flags & (HEXDUMP_2_GRP_SPACES | HEXDUMP_4_GRP_SPACES | + HEXDUMP_8_GRP_SPACES)) + *sep = ' '; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -107,6 +135,9 @@ static const char *group_separator(int group, u64 flags) * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups + * HEXDUMP_2_GRP_SPACES: insert a ' ' after every 2 groups + * HEXDUMP_4_GRP_SPACES: insert a ' ' after every 4 groups + * HEXDUMP_8_GRP_SPACES: insert a ' ' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -139,7 +170,8 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, int j, lx = 0; int ascii_column; int ret; - int line_chars = 0; + int sep_chars = 0; + char sep = 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -153,8 +185,14 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, len = rowsize; ngroups = len / groupsize; + ascii_column = rowsize * 2 + rowsize / groupsize + 1; + // space separators use 2 spaces in the hex output + separator_parameters(flags, groupsize, _chars, ); + if (sep == ' ') + ascii_column += rowsize / sep_chars; + if (!linebuflen) goto overflow1; @@ -222,24 +260,17 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, linebuf[lx++] = ' '; } - if (flags & HEXDUMP_2_GRP_LINES) - line_chars = groupsize * 2; - if (flags & HEXDUMP_4_GRP_LINES) - line_chars = groupsize * 4; - if (flags & HEXDUMP_8_GRP_LINES) - line_chars = groupsize * 8; - for (j = 0; j < len; j++) { if (linebuflen < lx + 2) goto overflow2; ch = ptr[j]; linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.'; - if (line_chars && ((j + 1) < len) && - ((j +
[PATCH v4 0/7] Hexdump Enhancements
From: Alastair D'Silva Apologies for the large CC list, it's a heads up for those responsible for subsystems where a prototype change in generic code causes a change in those subsystems. This series enhances hexdump. These improve the readability of the dumped data in certain situations (eg. wide terminals are available, many lines of empty bytes exist, etc). The default behaviour of hexdump is unchanged, however, the prototype for hex_dump_to_buffer() has changed, and print_hex_dump() has been renamed to print_hex_dump_ext(), with a wrapper replacing it for compatibility with existing code, which would have been too invasive to change. Hexdump selftests have be run & confirmed passed. Changelog: V4: - Add missing header (linux/bits.h) - Fix comment formatting - Create hex_dump_to_buffer_ext & make hex_dump_to_buffer a wrapper V3: - Fix inline documention - use BIT macros - use u32 rather than u64 for flags V2: - Fix failing selftests - Fix precedence bug in 'Replace ascii bool in hex_dump_to_buffer...' - Remove hardcoded new lengths & instead relax the checks in hex_dump_to_buffer, allocating the buffer from the heap instead of the stack. - Replace the skipping of lines of 0x00/0xff with skipping lines of repeated characters, announcing what has been skipped. - Add spaces as an optional N-group separator - Allow byte ordering to be maintained when HEXDUMP_RETAIN_BYTE_ORDERING is set. - Updated selftests to cover 'Relax rowsize checks' & 'Optionally retain byte ordering' Alastair D'Silva (7): lib/hexdump.c: Fix selftests lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer lib/hexdump.c: Optionally suppress lines of repeated bytes lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags lib/hexdump.c: Allow multiple groups to be separated by lines '|' lib/hexdump.c: Allow multiple groups to be separated by spaces lib/hexdump.c: Optionally retain byte ordering drivers/gpu/drm/i915/intel_engine_cs.c| 5 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 10 +- drivers/mailbox/mailbox-test.c| 8 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 7 +- .../net/wireless/intel/iwlegacy/3945-mac.c| 4 +- drivers/platform/chrome/wilco_ec/debugfs.c| 10 +- drivers/scsi/scsi_logging.c | 8 +- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 6 +- include/linux/printk.h| 75 - lib/hexdump.c | 267 +++--- lib/test_hexdump.c| 154 +++--- 14 files changed, 438 insertions(+), 122 deletions(-) -- 2.21.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v4 2/7] lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer
From: Alastair D'Silva This patch removes the hardcoded row limits and allows for other lengths. These lengths must still be a multiple of groupsize. This allows structs that are not 16/32 bytes to display on a single line. This patch also expands the self-tests to test row sizes up to 64 bytes (though they can now be arbitrarily long). Signed-off-by: Alastair D'Silva --- lib/hexdump.c | 49 +-- lib/test_hexdump.c | 52 ++ 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/lib/hexdump.c b/lib/hexdump.c index 81b70ed37209..870c8cbff1e1 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -12,6 +12,7 @@ #include #include #include +#include #include const char hex_asc[] = "0123456789abcdef"; @@ -80,14 +81,15 @@ EXPORT_SYMBOL(bin2hex); * 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 + * @rowsize: number of bytes to print per line; must be a multiple of groupsize * @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. + * hex_dump_to_buffer() works on one "line" of output at a time, converting + * bytes of input to hexadecimal (and optionally printable ASCII) + * until bytes have been emitted. * * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data * to a hex + ASCII dump at the supplied memory location. @@ -116,16 +118,17 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, 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; + if (rowsize % groupsize) + rowsize -= rowsize % groupsize; + + if (len > rowsize) /* limit to one line at a time */ + len = rowsize; + ngroups = len / groupsize; ascii_column = rowsize * 2 + rowsize / groupsize + 1; @@ -216,7 +219,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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 + * @rowsize: number of bytes to print per line; must be a multiple of groupsize * @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 @@ -226,10 +229,9 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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. + * lines of rowsize/groupsize groups of input data converted to hex + + * (optionally) ASCII output. * * E.g.: * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, @@ -246,17 +248,30 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, { const u8 *ptr = buf; int i, linelen, remaining = len; - unsigned char linebuf[32 * 3 + 2 + 32 + 1]; + unsigned char *linebuf; + unsigned int linebuf_len; - if (rowsize != 16 && rowsize != 32) - rowsize = 16; + if (rowsize % groupsize) + rowsize -= rowsize % groupsize; + + /* +* Worst case line length: +* 2 hex chars + space per byte in, 2 spaces, 1 char per byte in, NULL +*/ + linebuf_len = rowsize * 3 + 2 + rowsize + 1; + linebuf = kzalloc(linebuf_len, GFP_KERNEL); + if (!linebuf) { + printk("%s%shexdump: Could not alloc %u bytes for buffer\n", + level, prefix_str, linebuf_len); + return; + } for (i = 0; i < len; i += rowsize) { linelen = min(remaining, rowsize); remaining -= rowsize; hex_dump_to_buf
[PATCH v4 1/7] lib/hexdump.c: Fix selftests
From: Alastair D'Silva The overflow tests did not account for the situation where no overflow occurs and len < rowsize. This patch renames the cryptic variables and accounts for the above case. The selftests now pass. Signed-off-by: Alastair D'Silva --- lib/test_hexdump.c | 48 +++--- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/lib/test_hexdump.c b/lib/test_hexdump.c index 5144899d3c6b..bef97a964582 100644 --- a/lib/test_hexdump.c +++ b/lib/test_hexdump.c @@ -163,45 +163,53 @@ static void __init test_hexdump_overflow(size_t buflen, size_t len, { char test[TEST_HEXDUMP_BUF_SIZE]; char buf[TEST_HEXDUMP_BUF_SIZE]; - int rs = rowsize, gs = groupsize; - int ae, he, e, f, r; - bool a; + int ascii_len, hex_len, expected_len, fill_point, ngroups, rc; + bool match; total_tests++; memset(buf, FILL_CHAR, sizeof(buf)); - r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii); + rc = hex_dump_to_buffer(data_b, len, rowsize, groupsize, buf, buflen, + ascii); /* * Caller must provide the data length multiple of groupsize. The * calculations below are made with that assumption in mind. */ - ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */; - he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */; + ngroups = rowsize / groupsize; + hex_len = (groupsize * 2 /* hex */ + 1 /* spaces */) * ngroups + - 1 /* no trailing space */; + ascii_len = hex_len + 2 /* space */ + len /* ascii */; + + if (len < rowsize) { + ngroups = len / groupsize; + hex_len = (groupsize * 2 /* hex */ + 1 /* spaces */) * ngroups + - 1 /* no trailing space */; + } - if (ascii) - e = ae; - else - e = he; + expected_len = (ascii) ? ascii_len : hex_len; - f = min_t(int, e + 1, buflen); + fill_point = min_t(int, expected_len + 1, buflen); if (buflen) { - test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii); - test[f - 1] = '\0'; + test_hexdump_prepare_test(len, rowsize, groupsize, test, + sizeof(test), ascii); + test[fill_point - 1] = '\0'; } - memset(test + f, FILL_CHAR, sizeof(test) - f); + memset(test + fill_point, FILL_CHAR, sizeof(test) - fill_point); - a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE); + match = rc == expected_len && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE); buf[sizeof(buf) - 1] = '\0'; - if (!a) { - pr_err("Len: %zu buflen: %zu strlen: %zu\n", - len, buflen, strnlen(buf, sizeof(buf))); - pr_err("Result: %d '%s'\n", r, buf); - pr_err("Expect: %d '%s'\n", e, test); + if (!match) { + pr_err("rowsize: %u groupsize: %u ascii: %d Len: %zu buflen: %zu strlen: %zu\n", + rowsize, groupsize, ascii, len, buflen, + strnlen(buf, sizeof(buf))); + pr_err("Result: %d '%-.*s'\n", rc, (int)buflen, buf); + pr_err("Expect: %d '%-.*s'\n", expected_len, (int)buflen, test); failed_tests++; + } } -- 2.21.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva In order to support additional features, rename hex_dump_to_buffer to hex_dump_to_buffer_ext, and replace the ascii bool parameter with flags. A wrapper is provided for callers that do not need anything but a basic dump. Signed-off-by: Alastair D'Silva --- drivers/gpu/drm/i915/intel_engine_cs.c| 5 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 10 ++-- drivers/mailbox/mailbox-test.c| 8 ++-- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 7 +-- .../net/wireless/intel/iwlegacy/3945-mac.c| 4 +- drivers/platform/chrome/wilco_ec/debugfs.c| 10 ++-- drivers/scsi/scsi_logging.c | 8 ++-- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 6 ++- include/linux/printk.h| 46 +-- lib/hexdump.c | 24 +- lib/test_hexdump.c| 10 ++-- 14 files changed, 94 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index eea9bec04f1b..64189a0e5ec9 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1338,9 +1338,8 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len) } WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, - rowsize, sizeof(u32), - line, sizeof(line), - false) >= sizeof(line)); + rowsize, sizeof(u32), line, + sizeof(line)) >= sizeof(line)); drm_printf(m, "[%04zx] %s\n", pos, line); prev = buf + pos; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index fd5c52f37802..84455b521246 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -70,8 +70,9 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) int l = 0; while (l < (int)len) { - hex_dump_to_buffer(msg + l, len - l, 32, 1, - isar->log, 256, 1); + hex_dump_to_buffer_ext(msg + l, len - l, 32, 1, + isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; @@ -99,8 +100,9 @@ rcv_mbox(struct isar_hw *isar, u8 *msg) int l = 0; while (l < (int)isar->clsb) { - hex_dump_to_buffer(msg + l, isar->clsb - l, 32, - 1, isar->log, 256, 1); + hex_dump_to_buffer_ext(msg + l, isar->clsb - l, + 32, 1, isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c index 4555d678fadd..ce334f88a3ee 100644 --- a/drivers/mailbox/mailbox-test.c +++ b/drivers/mailbox/mailbox-test.c @@ -206,10 +206,10 @@ static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf, ptr = tdev->rx_buffer; while (l < MBOX_HEXDUMP_MAX_LEN) { - hex_dump_to_buffer(ptr, - MBOX_BYTES_PER_LINE, - MBOX_BYTES_PER_LINE, 1, touser + l, - MBOX_HEXDUMP_LINE_LEN, true); + hex_dump_to_buffer_ext(ptr, + MBOX_BYTES_PER_LINE, + MBOX_BYTES_PER_LINE, 1, touser + l, + MBOX_HEXDUMP_LINE_LEN, HEXDUMP_ASCII); ptr += MBOX_BYTES_PER_LINE; l += MBOX_HEXDUMP_LINE_LEN; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 3dd0cecddba8..f0118fe35c41 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -2992,7 +2992,7 @@ void xgbe_print_pkt(struct net_device
[PATCH v4 7/7] lib/hexdump.c: Optionally retain byte ordering
From: Alastair D'Silva The behaviour of hexdump groups is to print the data out as if it was a native-endian number. This patch tweaks the documentation to make this clear, and also adds the HEXDUMP_RETAIN_BYTE_ORDER flag to allow groups of multiple bytes to be printed without affecting the ordering of the printed bytes. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 1 + lib/hexdump.c | 30 lib/test_hexdump.c | 62 -- 3 files changed, 68 insertions(+), 25 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 1d082291facf..ed1a79aa9695 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -491,6 +491,7 @@ enum { #define HEXDUMP_2_GRP_SPACES BIT(5) #define HEXDUMP_4_GRP_SPACES BIT(6) #define HEXDUMP_8_GRP_SPACES BIT(7) +#define HEXDUMP_RETAIN_BYTE_ORDER BIT(8) extern int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index e09e3cf8e595..29024eccf5da 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -127,7 +127,8 @@ static void separator_parameters(u64 flags, int groupsize, int *sep_chars, * @buf: data blob to dump * @len: number of bytes in the @buf * @rowsize: number of bytes to print per line; must be a multiple of groupsize - * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1) + * @groupsize: number of bytes to convert to a native endian number and print: + *1, 2, 4, 8; default = 1 * @linebuf: where to put the converted data * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: @@ -138,6 +139,9 @@ static void separator_parameters(u64 flags, int groupsize, int *sep_chars, * HEXDUMP_2_GRP_SPACES: insert a ' ' after every 2 groups * HEXDUMP_4_GRP_SPACES: insert a ' ' after every 4 groups * HEXDUMP_8_GRP_SPACES: insert a ' ' after every 8 groups + * HEXDUMP_RETAIN_BYTE_ORDER: Retain the byte ordering of groups + * instead of treating each group as a + * native-endian number * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -172,6 +176,7 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, int ret; int sep_chars = 0; char sep = 0; + bool big_endian = (flags & HEXDUMP_RETAIN_BYTE_ORDER) ? 1 : 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -203,10 +208,13 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, const u64 *ptr8 = buf; for (j = 0; j < ngroups; j++) { + u64 val = big_endian ? + be64_to_cpu(get_unaligned(ptr8 + j)) : + get_unaligned(ptr8 + j); ret = snprintf(linebuf + lx, linebuflen - lx, "%s%16.16llx", j ? group_separator(j, flags) : "", - get_unaligned(ptr8 + j)); + val); if (ret >= linebuflen - lx) goto overflow1; lx += ret; @@ -215,10 +223,14 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, const u32 *ptr4 = buf; for (j = 0; j < ngroups; j++) { + u32 val = big_endian ? + be32_to_cpu(get_unaligned(ptr4 + j)) : + get_unaligned(ptr4 + j); + ret = snprintf(linebuf + lx, linebuflen - lx, "%s%8.8x", j ? group_separator(j, flags) : "", - get_unaligned(ptr4 + j)); + val); if (ret >= linebuflen - lx) goto overflow1; lx += ret; @@ -227,10 +239,14 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, const u16 *ptr2 = buf; for (j = 0; j < ngroups; j++) { + u16 val = big_endian ? + be16_to_cpu(get_unaligned(ptr2 + j)) : + get_unaligned(ptr2 + j); + ret = snprintf(linebuf + lx, linebuflen - lx,
[PATCH v4 5/7] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva With the wider display format, it can become hard to identify how many bytes into the line you are looking at. The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to print vertical lines to separate every N groups of bytes. eg. buf:: 454d414e 43415053|4e495f45 00584544 NAMESPAC|E_INDEX. buf:0010: 0002| | Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 +++ lib/hexdump.c | 59 -- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index f0761b3a2d5d..ae80d7af82ab 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -485,6 +485,9 @@ enum { #define HEXDUMP_ASCII BIT(0) #define HEXDUMP_SUPPRESS_REPEATED BIT(1) +#define HEXDUMP_2_GRP_LINESBIT(2) +#define HEXDUMP_4_GRP_LINESBIT(3) +#define HEXDUMP_8_GRP_LINESBIT(4) extern int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index 1bf838c1a568..4dcf759fe048 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -77,6 +77,23 @@ char *bin2hex(char *dst, const void *src, size_t count) } EXPORT_SYMBOL(bin2hex); +static const char *group_separator(int group, u64 flags) +{ + if (group == 0) + return " "; + + if ((flags & HEXDUMP_8_GRP_LINES) && !((group) % 8)) + return "|"; + + if ((flags & HEXDUMP_4_GRP_LINES) && !((group) % 4)) + return "|"; + + if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2)) + return "|"; + + return " "; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -87,6 +104,9 @@ EXPORT_SYMBOL(bin2hex); * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: * HEXDUMP_ASCII: include ASCII after the hex output + * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups + * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups + * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -119,6 +139,7 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, int j, lx = 0; int ascii_column; int ret; + int line_chars = 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -145,7 +166,8 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%16.16llx", j ? " " : "", + "%s%16.16llx", + j ? group_separator(j, flags) : "", get_unaligned(ptr8 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -156,7 +178,8 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%8.8x", j ? " " : "", + "%s%8.8x", + j ? group_separator(j, flags) : "", get_unaligned(ptr4 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -167,7 +190,8 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%4.4x", j ? " " : "", + "%s%4.4x", + j ? group_separator(j, flags) : "", get_unaligned(ptr2 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -197,11 +221,26 @@ int hex_dump_to_buffer_ext(const void *buf, size_t len, int rowsize, goto overflow2; linebuf[lx++] = ' '; } + + if
[PATCH v4 3/7] lib/hexdump.c: Optionally suppress lines of repeated bytes
From: Alastair D'Silva Some buffers may only be partially filled with useful data, while the rest is padded (typically with 0x00 or 0xff). This patch introduces a flag to allow the supression of lines of repeated bytes, which are replaced with '** Skipped %u bytes of value 0x%x **' An inline wrapper function is provided for backwards compatibility with existing code, which maintains the original behaviour. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 26 +--- lib/hexdump.c | 91 -- 2 files changed, 100 insertions(+), 17 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index cefd374c47b1..c0416d0eb9e2 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -7,6 +7,7 @@ #include #include #include +#include extern const char linux_banner[]; extern const char linux_proc_banner[]; @@ -481,13 +482,18 @@ enum { DUMP_PREFIX_ADDRESS, DUMP_PREFIX_OFFSET }; + extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, bool ascii); + +#define HEXDUMP_ASCII BIT(0) +#define HEXDUMP_SUPPRESS_REPEATED BIT(1) + #ifdef CONFIG_PRINTK -extern void print_hex_dump(const char *level, const char *prefix_str, +extern void print_hex_dump_ext(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, - const void *buf, size_t len, bool ascii); + const void *buf, size_t len, u32 flags); #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)\ dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) @@ -496,18 +502,28 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len); #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ #else -static inline void print_hex_dump(const char *level, const char *prefix_str, +static inline void print_hex_dump_ext(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, - const void *buf, size_t len, bool ascii) + const void *buf, size_t len, u32 flags) { } static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len) { } - #endif +static __always_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) +{ + print_hex_dump_ext(level, prefix_str, prefix_type, rowsize, groupsize, + buf, len, ascii ? HEXDUMP_ASCII : 0); +} + + #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ groupsize, buf, len, ascii)\ diff --git a/lib/hexdump.c b/lib/hexdump.c index 870c8cbff1e1..61dc625c32f5 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -212,8 +212,44 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, EXPORT_SYMBOL(hex_dump_to_buffer); #ifdef CONFIG_PRINTK + +/** + * buf_is_all - Check if a buffer contains only a single byte value + * @buf: pointer to the buffer + * @len: the size of the buffer in bytes + * @val: outputs the value if if the bytes are identical + */ +static bool buf_is_all(const u8 *buf, size_t len, u8 *val_out) +{ + size_t i; + u8 val; + + if (len <= 1) + return false; + + val = buf[0]; + + for (i = 1; i < len; i++) { + if (buf[i] != val) + return false; + } + + *val_out = val; + return true; +} + +static void announce_skipped(const char *level, const char *prefix_str, + u8 val, size_t count) +{ + if (count == 0) + return; + + printk("%s%s ** Skipped %lu bytes of value 0x%x **\n", + level, prefix_str, count, val); +} + /** - * print_hex_dump - print a text hex dump to syslog for a binary blob of data + * print_hex_dump_ext - dump a binary blob of data to syslog in hexadecimal * @level: kernel log level (e.g. KERN_DEBUG) * @prefix_str: string to prefix each line with; * caller supplies trailing spaces for alignment if desired @@ -224,6 +260,10 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * @buf: data blob to dump * @len: number of bytes in the @buf * @ascii: include ASCII after the hex output + * @flags: A bitwise OR of the
Re: [PATCH v4 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
On Mon, 2019-06-24 at 22:01 -0700, Joe Perches wrote: > On Tue, 2019-06-25 at 13:17 +1000, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > In order to support additional features, rename hex_dump_to_buffer > > to > > hex_dump_to_buffer_ext, and replace the ascii bool parameter with > > flags. > [] > > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c > > b/drivers/gpu/drm/i915/intel_engine_cs.c > [] > > @@ -1338,9 +1338,8 @@ static void hexdump(struct drm_printer *m, > > const void *buf, size_t len) > > } > > > > WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, > > - rowsize, sizeof(u32), > > - line, sizeof(line), > > - false) >= > > sizeof(line)); > > + rowsize, sizeof(u32), > > line, > > + sizeof(line)) >= > > sizeof(line)); > > Huh? Why do this? > > > diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c > > b/drivers/isdn/hardware/mISDN/mISDNisar.c > [] > > @@ -70,8 +70,9 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, > > u8 len, u8 *msg) > > int l = 0; > > > > while (l < (int)len) { > > - hex_dump_to_buffer(msg + l, len - l, > > 32, 1, > > - isar->log, 256, 1); > > + hex_dump_to_buffer_ext(msg + l, len - > > l, 32, 1, > > + isar->log, 256, > > + HEXDUMP_ASCII); > > Again, why do any of these? > > The point of the wrapper is to avoid changing these. > > The change actions Jani's suggestion: https://lkml.org/lkml/2019/6/20/343 -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 0/7] Hexdump Enhancements
On Wed, 2019-06-19 at 09:31 -0700, Joe Perches wrote: > On Mon, 2019-06-17 at 12:04 +1000, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > Apologies for the large CC list, it's a heads up for those > > responsible > > for subsystems where a prototype change in generic code causes a > > change > > in those subsystems. > > > > This series enhances hexdump. > > Still not a fan of these patches. I'm afraid there's not too much action I can take on that, I'm happy to address specific issues though. > > > These improve the readability of the dumped data in certain > > situations > > (eg. wide terminals are available, many lines of empty bytes exist, > > etc). > > Changing hexdump's last argument from bool to int is odd. > Think of it as replacing a single boolean with many booleans. > Perhaps a new function should be added instead of changing > the existing hexdump. > There's only a handful of consumers, I don't think there is a value-add in creating more wrappers vs updating the existing callers. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 0/7] Hexdump Enhancements
On Wed, 2019-06-19 at 17:35 -0700, Joe Perches wrote: > On Thu, 2019-06-20 at 09:15 +1000, Alastair D'Silva wrote: > > On Wed, 2019-06-19 at 09:31 -0700, Joe Perches wrote: > > > On Mon, 2019-06-17 at 12:04 +1000, Alastair D'Silva wrote: > > > > From: Alastair D'Silva > > > > > > > > Apologies for the large CC list, it's a heads up for those > > > > responsible > > > > for subsystems where a prototype change in generic code causes > > > > a > > > > change > > > > in those subsystems. > > > > > > > > This series enhances hexdump. > > > > > > Still not a fan of these patches. > > > > I'm afraid there's not too much action I can take on that, I'm > > happy to > > address specific issues though. > > > > > > These improve the readability of the dumped data in certain > > > > situations > > > > (eg. wide terminals are available, many lines of empty bytes > > > > exist, > > > > etc). > > I think it's generally overkill for the desired uses. I understand where you're coming from, however, these patches make it a lot easier to work with large chucks of binary data. I think it makes more sense to have these patches upstream, even though committed code may not necessarily have all the features enabled, as it means that devs won't have to apply out-of-tree patches during development to make larger dumps manageable. > > > > Changing hexdump's last argument from bool to int is odd. > > > > > > > Think of it as replacing a single boolean with many booleans. > > I understand it. It's odd. > > I would rather not have a mixture of true, false, and apparently > random collections of bitfields like 0xd or 0b1011 or their > equivalent or'd defines. > Where's the mixture? What would you propose instead? -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 2/7] lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer
On Mon, 2019-06-17 at 15:47 -0700, Randy Dunlap wrote: > Hi, > Just a comment style nit below... > > On 6/16/19 7:04 PM, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > This patch removes the hardcoded row limits and allows for > > other lengths. These lengths must still be a multiple of > > groupsize. > > > > This allows structs that are not 16/32 bytes to display on > > a single line. > > > > This patch also expands the self-tests to test row sizes > > up to 64 bytes (though they can now be arbitrarily long). > > > > Signed-off-by: Alastair D'Silva > > --- > > lib/hexdump.c | 48 -- > > lib/test_hexdump.c | 52 ++-- > > -- > > 2 files changed, 75 insertions(+), 25 deletions(-) > > > > diff --git a/lib/hexdump.c b/lib/hexdump.c > > index 81b70ed37209..3943507bc0e9 100644 > > --- a/lib/hexdump.c > > +++ b/lib/hexdump.c > > @@ -246,17 +248,29 @@ void print_hex_dump(const char *level, const > > char *prefix_str, int prefix_type, > > { > > const u8 *ptr = buf; > > int i, linelen, remaining = len; > > - unsigned char linebuf[32 * 3 + 2 + 32 + 1]; > > + unsigned char *linebuf; > > + unsigned int linebuf_len; > > > > - if (rowsize != 16 && rowsize != 32) > > - rowsize = 16; > > + if (rowsize % groupsize) > > + rowsize -= rowsize % groupsize; > > + > > + /* Worst case line length: > > +* 2 hex chars + space per byte in, 2 spaces, 1 char per byte > > in, NULL > > +*/ > > According to Documentation/process/coding-style.rst: > > The preferred style for long (multi-line) comments is: > > .. code-block:: c > > /* >* This is the preferred style for multi-line >* comments in the Linux kernel source code. >* Please use it consistently. >* >* Description: A column of asterisks on the left side, >* with beginning and ending almost-blank lines. >*/ > Thanks Randy, I'll address this. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 5/7] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva With the wider display format, it can become hard to identify how many bytes into the line you are looking at. The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to print vertical lines to separate every N groups of bytes. eg. buf:: 454d414e 43415053|4e495f45 00584544 NAMESPAC|E_INDEX. buf:0010: 0002| | Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 +++ lib/hexdump.c | 59 -- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 97dd29a2bd77..c6b748f66a82 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -484,6 +484,9 @@ enum { #define HEXDUMP_ASCII BIT(0) #define HEXDUMP_SUPPRESS_REPEATED BIT(1) +#define HEXDUMP_2_GRP_LINESBIT(2) +#define HEXDUMP_4_GRP_LINESBIT(3) +#define HEXDUMP_8_GRP_LINESBIT(4) extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index 08c6084d7daa..4da7d24826fb 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -77,6 +77,23 @@ char *bin2hex(char *dst, const void *src, size_t count) } EXPORT_SYMBOL(bin2hex); +static const char *group_separator(int group, u64 flags) +{ + if (group == 0) + return " "; + + if ((flags & HEXDUMP_8_GRP_LINES) && !((group) % 8)) + return "|"; + + if ((flags & HEXDUMP_4_GRP_LINES) && !((group) % 4)) + return "|"; + + if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2)) + return "|"; + + return " "; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -87,6 +104,9 @@ EXPORT_SYMBOL(bin2hex); * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: * HEXDUMP_ASCII: include ASCII after the hex output + * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups + * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups + * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -118,6 +138,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int j, lx = 0; int ascii_column; int ret; + int line_chars = 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -144,7 +165,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%16.16llx", j ? " " : "", + "%s%16.16llx", + j ? group_separator(j, flags) : "", get_unaligned(ptr8 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -155,7 +177,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%8.8x", j ? " " : "", + "%s%8.8x", + j ? group_separator(j, flags) : "", get_unaligned(ptr4 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -166,7 +189,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%4.4x", j ? " " : "", + "%s%4.4x", + j ? group_separator(j, flags) : "", get_unaligned(ptr2 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -196,11 +220,26 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, goto overflow2;
[PATCH v3 0/7] Hexdump Enhancements
From: Alastair D'Silva Apologies for the large CC list, it's a heads up for those responsible for subsystems where a prototype change in generic code causes a change in those subsystems. This series enhances hexdump. These improve the readability of the dumped data in certain situations (eg. wide terminals are available, many lines of empty bytes exist, etc). The default behaviour of hexdump is unchanged, however, the prototype for hex_dump_to_buffer() has changed, and print_hex_dump() has been renamed to print_hex_dump_ext(), with a wrapper replacing it for compatibility with existing code, which would have been too invasive to change. Hexdump selftests have be run & confirmed passed. Changelog: V3: - Fix inline documention - use BIT macros - use u32 rather than u64 for flags V2: - Fix failing selftests - Fix precedence bug in 'Replace ascii bool in hex_dump_to_buffer...' - Remove hardcoded new lengths & instead relax the checks in hex_dump_to_buffer, allocating the buffer from the heap instead of the stack. - Replace the skipping of lines of 0x00/0xff with skipping lines of repeated characters, announcing what has been skipped. - Add spaces as an optional N-group separator - Allow byte ordering to be maintained when HEXDUMP_RETAIN_BYTE_ORDERING is set. - Updated selftests to cover 'Relax rowsize checks' & 'Optionally retain byte ordering' Alastair D'Silva (7): lib/hexdump.c: Fix selftests lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer lib/hexdump.c: Optionally suppress lines of repeated bytes lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags lib/hexdump.c: Allow multiple groups to be separated by lines '|' lib/hexdump.c: Allow multiple groups to be separated by spaces lib/hexdump.c: Optionally retain byte ordering drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 6 +- drivers/mailbox/mailbox-test.c| 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 3 +- .../net/wireless/intel/iwlegacy/3945-mac.c| 2 +- drivers/platform/chrome/wilco_ec/debugfs.c| 2 +- drivers/scsi/scsi_logging.c | 8 +- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 3 +- include/linux/printk.h| 34 ++- lib/hexdump.c | 260 +++--- lib/test_hexdump.c| 146 +++--- 14 files changed, 372 insertions(+), 102 deletions(-) -- 2.21.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva In order to support additional features in hex_dump_to_buffer, replace the ascii bool parameter with flags. Signed-off-by: Alastair D'Silva --- drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 6 -- drivers/mailbox/mailbox-test.c| 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 3 ++- drivers/net/wireless/intel/iwlegacy/3945-mac.c| 2 +- drivers/platform/chrome/wilco_ec/debugfs.c| 2 +- drivers/scsi/scsi_logging.c | 8 +++- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 3 ++- include/linux/printk.h| 8 lib/hexdump.c | 15 --- lib/test_hexdump.c| 5 +++-- 14 files changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index eea9bec04f1b..5df5fffdb848 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1340,7 +1340,7 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len) WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, rowsize, sizeof(u32), line, sizeof(line), - false) >= sizeof(line)); + 0) >= sizeof(line)); drm_printf(m, "[%04zx] %s\n", pos, line); prev = buf + pos; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index fd5c52f37802..ccc0ee9d894f 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -71,7 +71,8 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) while (l < (int)len) { hex_dump_to_buffer(msg + l, len - l, 32, 1, - isar->log, 256, 1); + isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; @@ -100,7 +101,8 @@ rcv_mbox(struct isar_hw *isar, u8 *msg) while (l < (int)isar->clsb) { hex_dump_to_buffer(msg + l, isar->clsb - l, 32, - 1, isar->log, 256, 1); + 1, isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c index 4555d678fadd..23c3fbafdcb2 100644 --- a/drivers/mailbox/mailbox-test.c +++ b/drivers/mailbox/mailbox-test.c @@ -209,7 +209,7 @@ static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf, hex_dump_to_buffer(ptr, MBOX_BYTES_PER_LINE, MBOX_BYTES_PER_LINE, 1, touser + l, - MBOX_HEXDUMP_LINE_LEN, true); + MBOX_HEXDUMP_LINE_LEN, HEXDUMP_ASCII); ptr += MBOX_BYTES_PER_LINE; l += MBOX_HEXDUMP_LINE_LEN; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 3dd0cecddba8..1e26410cf6c2 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -2992,7 +2992,7 @@ void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) unsigned int len = min(skb->len - i, 32U); hex_dump_to_buffer(>data[i], len, 32, 1, - buffer, sizeof(buffer), false); + buffer, sizeof(buffer), 0); netdev_dbg(netdev, " %#06x: %s\n", i, buffer); } diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c index eb1c6b03c329..b80adfa1f890 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c @@ -349,7 +349,7 @@ void xlgmac_
[PATCH v3 1/7] lib/hexdump.c: Fix selftests
From: Alastair D'Silva The overflow tests did not account for the situation where no overflow occurs and len < rowsize. This patch renames the cryptic variables and accounts for the above case. The selftests now pass. Signed-off-by: Alastair D'Silva --- lib/test_hexdump.c | 47 ++ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/lib/test_hexdump.c b/lib/test_hexdump.c index 5144899d3c6b..d78ddd62ffd0 100644 --- a/lib/test_hexdump.c +++ b/lib/test_hexdump.c @@ -163,45 +163,52 @@ static void __init test_hexdump_overflow(size_t buflen, size_t len, { char test[TEST_HEXDUMP_BUF_SIZE]; char buf[TEST_HEXDUMP_BUF_SIZE]; - int rs = rowsize, gs = groupsize; - int ae, he, e, f, r; - bool a; + int ascii_len, hex_len, expected_len, fill_point, ngroups, rc; + bool match; total_tests++; memset(buf, FILL_CHAR, sizeof(buf)); - r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii); + rc = hex_dump_to_buffer(data_b, len, rowsize, groupsize, buf, buflen, ascii); /* * Caller must provide the data length multiple of groupsize. The * calculations below are made with that assumption in mind. */ - ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */; - he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */; + ngroups = rowsize / groupsize; + hex_len = (groupsize * 2 /* hex */ + 1 /* spaces */) * ngroups + - 1 /* no trailing space */; + ascii_len = hex_len + 2 /* space */ + len /* ascii */; + + if (len < rowsize) { + ngroups = len / groupsize; + hex_len = (groupsize * 2 /* hex */ + 1 /* spaces */) * ngroups + - 1 /* no trailing space */; + } - if (ascii) - e = ae; - else - e = he; + expected_len = (ascii) ? ascii_len : hex_len; - f = min_t(int, e + 1, buflen); + fill_point = min_t(int, expected_len + 1, buflen); if (buflen) { - test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii); - test[f - 1] = '\0'; + test_hexdump_prepare_test(len, rowsize, groupsize, test, + sizeof(test), ascii); + test[fill_point - 1] = '\0'; } - memset(test + f, FILL_CHAR, sizeof(test) - f); + memset(test + fill_point, FILL_CHAR, sizeof(test) - fill_point); - a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE); + match = rc == expected_len && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE); buf[sizeof(buf) - 1] = '\0'; - if (!a) { - pr_err("Len: %zu buflen: %zu strlen: %zu\n", - len, buflen, strnlen(buf, sizeof(buf))); - pr_err("Result: %d '%s'\n", r, buf); - pr_err("Expect: %d '%s'\n", e, test); + if (!match) { + pr_err("rowsize: %u groupsize: %u ascii: %d Len: %zu buflen: %zu strlen: %zu\n", + rowsize, groupsize, ascii, len, buflen, + strnlen(buf, sizeof(buf))); + pr_err("Result: %d '%-.*s'\n", rc, (int)buflen, buf); + pr_err("Expect: %d '%-.*s'\n", expected_len, (int)buflen, test); failed_tests++; + } } -- 2.21.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 7/7] lib/hexdump.c: Optionally retain byte ordering
From: Alastair D'Silva The behaviour of hexdump groups is to print the data out as if it was a native-endian number. This patch tweaks the documentation to make this clear, and also adds the HEXDUMP_RETAIN_BYTE_ORDER flag to allow groups of multiple bytes to be printed without affecting the ordering of the printed bytes. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 1 + lib/hexdump.c | 30 + lib/test_hexdump.c | 60 +- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 04416e788802..ffc94bedd737 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -490,6 +490,7 @@ enum { #define HEXDUMP_2_GRP_SPACES BIT(5) #define HEXDUMP_4_GRP_SPACES BIT(6) #define HEXDUMP_8_GRP_SPACES BIT(7) +#define HEXDUMP_RETAIN_BYTE_ORDER BIT(8) extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index dc85ef0dbb0a..ce14abc7701f 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -127,7 +127,8 @@ static void separator_parameters(u64 flags, int groupsize, int *sep_chars, * @buf: data blob to dump * @len: number of bytes in the @buf * @rowsize: number of bytes to print per line; must be a multiple of groupsize - * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1) + * @groupsize: number of bytes to convert to a native endian number and print: + *1, 2, 4, 8; default = 1 * @linebuf: where to put the converted data * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: @@ -138,6 +139,9 @@ static void separator_parameters(u64 flags, int groupsize, int *sep_chars, * HEXDUMP_2_GRP_SPACES: insert a ' ' after every 2 groups * HEXDUMP_4_GRP_SPACES: insert a ' ' after every 4 groups * HEXDUMP_8_GRP_SPACES: insert a ' ' after every 8 groups + * HEXDUMP_RETAIN_BYTE_ORDER: Retain the byte ordering of groups + * instead of treating each group as a + * native-endian number * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -171,6 +175,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int ret; int sep_chars = 0; char sep = 0; + bool big_endian = (flags & HEXDUMP_RETAIN_BYTE_ORDER) ? 1 : 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -202,10 +207,13 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, const u64 *ptr8 = buf; for (j = 0; j < ngroups; j++) { + u64 val = big_endian ? + be64_to_cpu(get_unaligned(ptr8 + j)) : + get_unaligned(ptr8 + j); ret = snprintf(linebuf + lx, linebuflen - lx, "%s%16.16llx", j ? group_separator(j, flags) : "", - get_unaligned(ptr8 + j)); + val); if (ret >= linebuflen - lx) goto overflow1; lx += ret; @@ -214,10 +222,14 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, const u32 *ptr4 = buf; for (j = 0; j < ngroups; j++) { + u32 val = big_endian ? + be32_to_cpu(get_unaligned(ptr4 + j)) : + get_unaligned(ptr4 + j); + ret = snprintf(linebuf + lx, linebuflen - lx, "%s%8.8x", j ? group_separator(j, flags) : "", - get_unaligned(ptr4 + j)); + val); if (ret >= linebuflen - lx) goto overflow1; lx += ret; @@ -226,10 +238,14 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, const u16 *ptr2 = buf; for (j = 0; j < ngroups; j++) { + u16 val = big_endian ? + be16_to_cpu(get_unaligned(ptr2 + j)) : + get_unaligned(ptr2 + j); + ret = snprintf(linebu
[PATCH v3 3/7] lib/hexdump.c: Optionally suppress lines of repeated bytes
From: Alastair D'Silva Some buffers may only be partially filled with useful data, while the rest is padded (typically with 0x00 or 0xff). This patch introduces a flag to allow the supression of lines of repeated bytes, which are replaced with '** Skipped %u bytes of value 0x%x **' An inline wrapper function is provided for backwards compatibility with existing code, which maintains the original behaviour. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 25 +--- lib/hexdump.c | 91 -- 2 files changed, 99 insertions(+), 17 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index cefd374c47b1..d7754799cfe0 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -481,13 +481,18 @@ enum { DUMP_PREFIX_ADDRESS, DUMP_PREFIX_OFFSET }; + extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, bool ascii); + +#define HEXDUMP_ASCII BIT(0) +#define HEXDUMP_SUPPRESS_REPEATED BIT(1) + #ifdef CONFIG_PRINTK -extern void print_hex_dump(const char *level, const char *prefix_str, +extern void print_hex_dump_ext(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, - const void *buf, size_t len, bool ascii); + const void *buf, size_t len, u32 flags); #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)\ dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) @@ -496,18 +501,28 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len); #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ #else -static inline void print_hex_dump(const char *level, const char *prefix_str, +static inline void print_hex_dump_ext(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, - const void *buf, size_t len, bool ascii) + const void *buf, size_t len, u32 flags) { } static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len) { } - #endif +static __always_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) +{ + print_hex_dump_ext(level, prefix_str, prefix_type, rowsize, groupsize, + buf, len, ascii ? HEXDUMP_ASCII : 0); +} + + #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ groupsize, buf, len, ascii)\ diff --git a/lib/hexdump.c b/lib/hexdump.c index 3943507bc0e9..b781f84e 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -212,8 +212,44 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, EXPORT_SYMBOL(hex_dump_to_buffer); #ifdef CONFIG_PRINTK + +/** + * buf_is_all - Check if a buffer contains only a single byte value + * @buf: pointer to the buffer + * @len: the size of the buffer in bytes + * @val: outputs the value if if the bytes are identical + */ +static bool buf_is_all(const u8 *buf, size_t len, u8 *val_out) +{ + size_t i; + u8 val; + + if (len <= 1) + return false; + + val = buf[0]; + + for (i = 1; i < len; i++) { + if (buf[i] != val) + return false; + } + + *val_out = val; + return true; +} + +static void announce_skipped(const char *level, const char *prefix_str, + u8 val, size_t count) +{ + if (count == 0) + return; + + printk("%s%s ** Skipped %lu bytes of value 0x%x **\n", + level, prefix_str, count, val); +} + /** - * print_hex_dump - print a text hex dump to syslog for a binary blob of data + * print_hex_dump_ext - dump a binary blob of data to syslog in hexadecimal * @level: kernel log level (e.g. KERN_DEBUG) * @prefix_str: string to prefix each line with; * caller supplies trailing spaces for alignment if desired @@ -224,6 +260,10 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * @buf: data blob to dump * @len: number of bytes in the @buf * @ascii: include ASCII after the hex output + * @flags: A bitwise OR of the following flags: + * HEXDUMP_ASCII: include ASCII after the hex output + * HEXDUMP_SUPPRESS_REPEATED: suppress repeated li
[PATCH v3 2/7] lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer
From: Alastair D'Silva This patch removes the hardcoded row limits and allows for other lengths. These lengths must still be a multiple of groupsize. This allows structs that are not 16/32 bytes to display on a single line. This patch also expands the self-tests to test row sizes up to 64 bytes (though they can now be arbitrarily long). Signed-off-by: Alastair D'Silva --- lib/hexdump.c | 48 -- lib/test_hexdump.c | 52 ++ 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/lib/hexdump.c b/lib/hexdump.c index 81b70ed37209..3943507bc0e9 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -12,6 +12,7 @@ #include #include #include +#include #include const char hex_asc[] = "0123456789abcdef"; @@ -80,14 +81,15 @@ EXPORT_SYMBOL(bin2hex); * 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 + * @rowsize: number of bytes to print per line; must be a multiple of groupsize * @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. + * hex_dump_to_buffer() works on one "line" of output at a time, converting + * bytes of input to hexadecimal (and optionally printable ASCII) + * until bytes have been emitted. * * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data * to a hex + ASCII dump at the supplied memory location. @@ -116,16 +118,17 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, 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; + if (rowsize % groupsize) + rowsize -= rowsize % groupsize; + + if (len > rowsize) /* limit to one line at a time */ + len = rowsize; + ngroups = len / groupsize; ascii_column = rowsize * 2 + rowsize / groupsize + 1; @@ -216,7 +219,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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 + * @rowsize: number of bytes to print per line; must be a multiple of groupsize * @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 @@ -226,10 +229,9 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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. + * lines of rowsize/groupsize groups of input data converted to hex + + * (optionally) ASCII output. * * E.g.: * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, @@ -246,17 +248,29 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, { const u8 *ptr = buf; int i, linelen, remaining = len; - unsigned char linebuf[32 * 3 + 2 + 32 + 1]; + unsigned char *linebuf; + unsigned int linebuf_len; - if (rowsize != 16 && rowsize != 32) - rowsize = 16; + if (rowsize % groupsize) + rowsize -= rowsize % groupsize; + + /* Worst case line length: +* 2 hex chars + space per byte in, 2 spaces, 1 char per byte in, NULL +*/ + linebuf_len = rowsize * 3 + 2 + rowsize + 1; + linebuf = kzalloc(linebuf_len, GFP_KERNEL); + if (!linebuf) { + printk("%s%shexdump: Could not alloc %u bytes for buffer\n", + level, prefix_str, linebuf_len); + return; + } for (i = 0; i < len; i += rowsize) { linelen = min(remaining, rowsize); remaining -= rowsize; hex_dump_to_buf
Re: [PATCH v3 3/7] lib/hexdump.c: Optionally suppress lines of repeated bytes
On Mon, 2019-06-17 at 12:04 +1000, Alastair D'Silva wrote: > From: Alastair D'Silva > > Some buffers may only be partially filled with useful data, while the > rest > is padded (typically with 0x00 or 0xff). > > This patch introduces a flag to allow the supression of lines of > repeated > bytes, which are replaced with '** Skipped %u bytes of value 0x%x **' > > An inline wrapper function is provided for backwards compatibility > with > existing code, which maintains the original behaviour. > > Signed-off-by: Alastair D'Silva > --- > include/linux/printk.h | 25 +--- > lib/hexdump.c | 91 -- > > 2 files changed, 99 insertions(+), 17 deletions(-) > > diff --git a/include/linux/printk.h b/include/linux/printk.h > index cefd374c47b1..d7754799cfe0 100644 > --- a/include/linux/printk.h > +++ b/include/linux/printk.h > @@ -481,13 +481,18 @@ enum { > DUMP_PREFIX_ADDRESS, > DUMP_PREFIX_OFFSET > }; > + > extern int hex_dump_to_buffer(const void *buf, size_t len, int > rowsize, > int groupsize, char *linebuf, size_t > linebuflen, > bool ascii); > + > +#define HEXDUMP_ASCIIBIT(0) > +#define HEXDUMP_SUPPRESS_REPEATED BIT(1) > + This is missing the include of linux/bits.h, I'll fix this in the next version. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 6/7] lib/hexdump.c: Allow multiple groups to be separated by spaces
From: Alastair D'Silva Similar to the previous patch, this patch separates groups by 2 spaces for the hex fields, and 1 space for the ASCII field. eg. buf:: 454d414e 43415053 4e495f45 00584544 NAMESPAC E_INDEX. buf:0010: 0002 Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 ++ lib/hexdump.c | 65 +++--- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index c6b748f66a82..04416e788802 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -487,6 +487,9 @@ enum { #define HEXDUMP_2_GRP_LINESBIT(2) #define HEXDUMP_4_GRP_LINESBIT(3) #define HEXDUMP_8_GRP_LINESBIT(4) +#define HEXDUMP_2_GRP_SPACES BIT(5) +#define HEXDUMP_4_GRP_SPACES BIT(6) +#define HEXDUMP_8_GRP_SPACES BIT(7) extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index 4da7d24826fb..dc85ef0dbb0a 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -91,9 +91,37 @@ static const char *group_separator(int group, u64 flags) if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2)) return "|"; + if ((flags & HEXDUMP_8_GRP_SPACES) && !((group) % 8)) + return " "; + + if ((flags & HEXDUMP_4_GRP_SPACES) && !((group) % 4)) + return " "; + + if ((flags & HEXDUMP_2_GRP_SPACES) && !((group) % 2)) + return " "; + return " "; } +static void separator_parameters(u64 flags, int groupsize, int *sep_chars, +char *sep) +{ + if (flags & (HEXDUMP_2_GRP_LINES | HEXDUMP_2_GRP_SPACES)) + *sep_chars = groupsize * 2; + if (flags & (HEXDUMP_4_GRP_LINES | HEXDUMP_4_GRP_SPACES)) + *sep_chars = groupsize * 4; + if (flags & (HEXDUMP_8_GRP_LINES | HEXDUMP_8_GRP_SPACES)) + *sep_chars = groupsize * 8; + + if (flags & (HEXDUMP_2_GRP_LINES | HEXDUMP_4_GRP_LINES | + HEXDUMP_8_GRP_LINES)) + *sep = '|'; + + if (flags & (HEXDUMP_2_GRP_SPACES | HEXDUMP_4_GRP_SPACES | + HEXDUMP_8_GRP_SPACES)) + *sep = ' '; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -107,6 +135,9 @@ static const char *group_separator(int group, u64 flags) * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups + * HEXDUMP_2_GRP_SPACES: insert a ' ' after every 2 groups + * HEXDUMP_4_GRP_SPACES: insert a ' ' after every 4 groups + * HEXDUMP_8_GRP_SPACES: insert a ' ' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -138,7 +169,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int j, lx = 0; int ascii_column; int ret; - int line_chars = 0; + int sep_chars = 0; + char sep = 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -152,8 +184,14 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, len = rowsize; ngroups = len / groupsize; + ascii_column = rowsize * 2 + rowsize / groupsize + 1; + // space separators use 2 spaces in the hex output + separator_parameters(flags, groupsize, _chars, ); + if (sep == ' ') + ascii_column += rowsize / sep_chars; + if (!linebuflen) goto overflow1; @@ -221,24 +259,17 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, linebuf[lx++] = ' '; } - if (flags & HEXDUMP_2_GRP_LINES) - line_chars = groupsize * 2; - if (flags & HEXDUMP_4_GRP_LINES) - line_chars = groupsize * 4; - if (flags & HEXDUMP_8_GRP_LINES) - line_chars = groupsize * 8; - for (j = 0; j < len; j++) { if (linebuflen < lx + 2) goto overflow2; ch = ptr[j]; linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.'; - if (line_chars && ((j + 1) < len) && - ((j +
RE: [PATCH v2 3/7] lib/hexdump.c: Optionally suppress lines of repeated bytes
> -Original Message- > From: Geert Uytterhoeven > Sent: Monday, 13 May 2019 5:01 PM > To: Alastair D'Silva > Cc: alast...@d-silva.org; Jani Nikula ; Joonas > Lahtinen ; Rodrigo Vivi > ; David Airlie ; Daniel Vetter > ; Dan Carpenter ; Karsten > Keil ; Jassi Brar ; Tom > Lendacky ; David S. Miller > ; Jose Abreu ; Kalle > Valo ; Stanislaw Gruszka ; > Benson Leung ; Enric Balletbo i Serra > ; James E.J. Bottomley > ; Martin K. Petersen ; > Greg Kroah-Hartman ; Alexander Viro > ; Petr Mladek ; Sergey > Senozhatsky ; Steven Rostedt > ; David Laight ; Andrew > Morton ; Intel Graphics Development g...@lists.freedesktop.org>; DRI Development de...@lists.freedesktop.org>; Linux Kernel Mailing List ker...@vger.kernel.org>; netdev ; > ath...@lists.infradead.org; linux-wireless ; > scsi ; Linux Fbdev development list fb...@vger.kernel.org>; driverdevel ; Linux > FS Devel > Subject: Re: [PATCH v2 3/7] lib/hexdump.c: Optionally suppress lines of > repeated bytes > > Hi Alastair, > > Thanks for your patch! And thanks for your politeness :) > > On Wed, May 8, 2019 at 9:04 AM Alastair D'Silva > wrote: > > From: Alastair D'Silva > > > > Some buffers may only be partially filled with useful data, while the > > rest is padded (typically with 0x00 or 0xff). > > > > This patch introduces a flag to allow the supression of lines of > > repeated bytes, > > Given print_hex_dump() operates on entities of groupsize (1, 2, 4, or 8) > bytes, wouldn't it make more sense to consider repeated groups instead of > repeated bytes? Maybe, it would mean that subsequent addresses may not be a multiple of rowsize though, which is useful. > > which are replaced with '** Skipped %u bytes of value 0x%x **' > > Using a custom message instead of just "*", like "hexdump" uses, will require > preprocessing the output when recovering the original binary data by > feeding it to e.g. "xxd". > This may sound worse than it is, though, as I never got "xxd" to work without > preprocessing anyway ;-) I think showing the details of the skipped values is useful when reading the output directly. In situations where binary extracts are desired, the feature can always be disabled. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 3/7] lib/hexdump.c: Optionally suppress lines of repeated bytes
On Wed, 2019-05-08 at 17:58 -0700, Randy Dunlap wrote: > On 5/8/19 12:01 AM, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > Some buffers may only be partially filled with useful data, while > > the rest > > is padded (typically with 0x00 or 0xff). > > > > This patch introduces a flag to allow the supression of lines of > > repeated > > bytes, which are replaced with '** Skipped %u bytes of value 0x%x > > **' > > > > An inline wrapper function is provided for backwards compatibility > > with > > existing code, which maintains the original behaviour. > > > > Signed-off-by: Alastair D'Silva > > --- > > include/linux/printk.h | 25 +--- > > lib/hexdump.c | 91 > > -- > > 2 files changed, 99 insertions(+), 17 deletions(-) > > > > Hi, > Did you do "make htmldocs" or something similar on this? > > > diff --git a/lib/hexdump.c b/lib/hexdump.c > > index 3943507bc0e9..d61a1e4f19fa 100644 > > --- a/lib/hexdump.c > > +++ b/lib/hexdump.c > > @@ -212,8 +212,44 @@ int hex_dump_to_buffer(const void *buf, size_t > > len, int rowsize, int groupsize, > > EXPORT_SYMBOL(hex_dump_to_buffer); > > > > #ifdef CONFIG_PRINTK > > + > > +/** > > + * Check if a buffer contains only a single byte value > > + * @buf: pointer to the buffer > > + * @len: the size of the buffer in bytes > > + * @val: outputs the value if if the bytes are identical > > Does this work without a function name? > Documentation/doc-guide/kernel-doc.rst says the general format is: > > /** >* function_name() - Brief description of function. >* @arg1: Describe the first argument. >* @arg2: Describe the second argument. >*One can provide multiple line descriptions >*for arguments. >* > > > + */ > > /** > > - * print_hex_dump - print a text hex dump to syslog for a binary > > blob of data > > + * print_hex_dump_ext: dump a binary blob of data to syslog in > > hexadecimal > > Also not in the general documented format. > Thanks Randy, I'll address these. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 0/7] Hexdump Enhancements
From: Alastair D'Silva Apologies for the large CC list, it's a heads up for those responsible for subsystems where a prototype change in generic code causes a change in those subsystems. This series enhances hexdump. These improve the readability of the dumped data in certain situations (eg. wide terminals are available, many lines of empty bytes exist, etc). The default behaviour of hexdump is unchanged, however, the prototype for hex_dump_to_buffer() has changed, and print_hex_dump() has been renamed to print_hex_dump_ext(), with a wrapper replacing it for compatibility with existing code, which would have been too invasive to change. Hexdump selftests have be run & confirmed passed. Changelog: - Fix failing selftests - Fix precedence bug in 'Replace ascii bool in hex_dump_to_buffer...' - Remove hardcoded new lengths & instead relax the checks in hex_dump_to_buffer, allocating the buffer from the heap instead of the stack. - Replace the skipping of lines of 0x00/0xff with skipping lines of repeated characters, announcing what has been skipped. - Add spaces as an optional N-group separator - Allow byte ordering to be maintained when HEXDUMP_RETAIN_BYTE_ORDERING is set. - Updated selftests to cover 'Relax rowsize checks' & 'Optionally retain byte ordering' Alastair D'Silva (7): lib/hexdump.c: Fix selftests lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer lib/hexdump.c: Optionally suppress lines of repeated bytes lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags lib/hexdump.c: Allow multiple groups to be separated by lines '|' lib/hexdump.c: Allow multiple groups to be separated by spaces lib/hexdump.c: Optionally retain byte ordering drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 6 +- drivers/mailbox/mailbox-test.c| 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 3 +- .../net/wireless/intel/iwlegacy/3945-mac.c| 2 +- drivers/platform/chrome/wilco_ec/debugfs.c| 2 +- drivers/scsi/scsi_logging.c | 8 +- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 3 +- include/linux/printk.h| 34 ++- lib/hexdump.c | 260 +++--- lib/test_hexdump.c| 146 +++--- 14 files changed, 372 insertions(+), 102 deletions(-) -- 2.21.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 6/7] lib/hexdump.c: Allow multiple groups to be separated by spaces
From: Alastair D'Silva Similar to the previous patch, this patch separates groups by 2 spaces for the hex fields, and 1 space for the ASCII field. eg. buf:: 454d414e 43415053 4e495f45 00584544 NAMESPAC E_INDEX. buf:0010: 0002 Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 ++ lib/hexdump.c | 65 +++--- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index dc693aec394c..5231a14e4593 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -485,6 +485,9 @@ enum { #define HEXDUMP_2_GRP_LINES(1 << 2) #define HEXDUMP_4_GRP_LINES(1 << 3) #define HEXDUMP_8_GRP_LINES(1 << 4) +#define HEXDUMP_2_GRP_SPACES (1 << 5) +#define HEXDUMP_4_GRP_SPACES (1 << 6) +#define HEXDUMP_8_GRP_SPACES (1 << 7) extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index 6f4d1176c332..febd614406d1 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -91,9 +91,37 @@ static const char *group_separator(int group, u64 flags) if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2)) return "|"; + if ((flags & HEXDUMP_8_GRP_SPACES) && !((group) % 8)) + return " "; + + if ((flags & HEXDUMP_4_GRP_SPACES) && !((group) % 4)) + return " "; + + if ((flags & HEXDUMP_2_GRP_SPACES) && !((group) % 2)) + return " "; + return " "; } +static void separator_parameters(u64 flags, int groupsize, int *sep_chars, +char *sep) +{ + if (flags & (HEXDUMP_2_GRP_LINES | HEXDUMP_2_GRP_SPACES)) + *sep_chars = groupsize * 2; + if (flags & (HEXDUMP_4_GRP_LINES | HEXDUMP_4_GRP_SPACES)) + *sep_chars = groupsize * 4; + if (flags & (HEXDUMP_8_GRP_LINES | HEXDUMP_8_GRP_SPACES)) + *sep_chars = groupsize * 8; + + if (flags & (HEXDUMP_2_GRP_LINES | HEXDUMP_4_GRP_LINES | + HEXDUMP_8_GRP_LINES)) + *sep = '|'; + + if (flags & (HEXDUMP_2_GRP_SPACES | HEXDUMP_4_GRP_SPACES | + HEXDUMP_8_GRP_SPACES)) + *sep = ' '; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -107,6 +135,9 @@ static const char *group_separator(int group, u64 flags) * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups + * HEXDUMP_2_GRP_SPACES: insert a ' ' after every 2 groups + * HEXDUMP_4_GRP_SPACES: insert a ' ' after every 4 groups + * HEXDUMP_8_GRP_SPACES: insert a ' ' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -138,7 +169,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int j, lx = 0; int ascii_column; int ret; - int line_chars = 0; + int sep_chars = 0; + char sep = 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -152,8 +184,14 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, len = rowsize; ngroups = len / groupsize; + ascii_column = rowsize * 2 + rowsize / groupsize + 1; + // space separators use 2 spaces in the hex output + separator_parameters(flags, groupsize, _chars, ); + if (sep == ' ') + ascii_column += rowsize / sep_chars; + if (!linebuflen) goto overflow1; @@ -221,24 +259,17 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, linebuf[lx++] = ' '; } - if (flags & HEXDUMP_2_GRP_LINES) - line_chars = groupsize * 2; - if (flags & HEXDUMP_4_GRP_LINES) - line_chars = groupsize * 4; - if (flags & HEXDUMP_8_GRP_LINES) - line_chars = groupsize * 8; - for (j = 0; j < len; j++) { if (linebuflen < lx + 2) goto overflow2; ch = ptr[j]; linebuf[lx++] = (isascii(ch) && isprint(ch)) ? ch : '.'; - if (line_chars && ((j + 1) < len) &
[PATCH v2 3/7] lib/hexdump.c: Optionally suppress lines of repeated bytes
From: Alastair D'Silva Some buffers may only be partially filled with useful data, while the rest is padded (typically with 0x00 or 0xff). This patch introduces a flag to allow the supression of lines of repeated bytes, which are replaced with '** Skipped %u bytes of value 0x%x **' An inline wrapper function is provided for backwards compatibility with existing code, which maintains the original behaviour. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 25 +--- lib/hexdump.c | 91 -- 2 files changed, 99 insertions(+), 17 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index d7c77ed1a4cb..938a67580d78 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -479,13 +479,18 @@ enum { DUMP_PREFIX_ADDRESS, DUMP_PREFIX_OFFSET }; + extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, bool ascii); + +#define HEXDUMP_ASCII (1 << 0) +#define HEXDUMP_SUPPRESS_REPEATED (1 << 1) + #ifdef CONFIG_PRINTK -extern void print_hex_dump(const char *level, const char *prefix_str, +extern void print_hex_dump_ext(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, - const void *buf, size_t len, bool ascii); + const void *buf, size_t len, u64 flags); #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)\ dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) @@ -494,18 +499,28 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len); #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ #else -static inline void print_hex_dump(const char *level, const char *prefix_str, +static inline void print_hex_dump_ext(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, - const void *buf, size_t len, bool ascii) + const void *buf, size_t len, u64 flags) { } static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len) { } - #endif +static __always_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) +{ + print_hex_dump_ext(level, prefix_str, prefix_type, rowsize, groupsize, + buf, len, ascii ? HEXDUMP_ASCII : 0); +} + + #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ groupsize, buf, len, ascii)\ diff --git a/lib/hexdump.c b/lib/hexdump.c index 3943507bc0e9..d61a1e4f19fa 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -212,8 +212,44 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, EXPORT_SYMBOL(hex_dump_to_buffer); #ifdef CONFIG_PRINTK + +/** + * Check if a buffer contains only a single byte value + * @buf: pointer to the buffer + * @len: the size of the buffer in bytes + * @val: outputs the value if if the bytes are identical + */ +static bool buf_is_all(const u8 *buf, size_t len, u8 *val_out) +{ + size_t i; + u8 val; + + if (len <= 1) + return false; + + val = buf[0]; + + for (i = 1; i < len; i++) { + if (buf[i] != val) + return false; + } + + *val_out = val; + return true; +} + +static void announce_skipped(const char *level, const char *prefix_str, + u8 val, size_t count) +{ + if (count == 0) + return; + + printk("%s%s ** Skipped %lu bytes of value 0x%x **\n", + level, prefix_str, count, val); +} + /** - * print_hex_dump - print a text hex dump to syslog for a binary blob of data + * print_hex_dump_ext: dump a binary blob of data to syslog in hexadecimal * @level: kernel log level (e.g. KERN_DEBUG) * @prefix_str: string to prefix each line with; * caller supplies trailing spaces for alignment if desired @@ -224,6 +260,10 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * @buf: data blob to dump * @len: number of bytes in the @buf * @ascii: include ASCII after the hex output + * @flags: A bitwise OR of the following flags: + * HEXDUMP_ASCII: include ASCII after the hex output + * HEXDUMP_SUPPRESS_REPEATED: suppress
[PATCH v2 1/7] lib/hexdump.c: Fix selftests
From: Alastair D'Silva The overflow tests did not account for the situation where no overflow occurs and len < rowsize. This patch renames the cryptic variables and accounts for the above case. The selftests now pass. Signed-off-by: Alastair D'Silva --- lib/test_hexdump.c | 47 ++ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/lib/test_hexdump.c b/lib/test_hexdump.c index 5144899d3c6b..d78ddd62ffd0 100644 --- a/lib/test_hexdump.c +++ b/lib/test_hexdump.c @@ -163,45 +163,52 @@ static void __init test_hexdump_overflow(size_t buflen, size_t len, { char test[TEST_HEXDUMP_BUF_SIZE]; char buf[TEST_HEXDUMP_BUF_SIZE]; - int rs = rowsize, gs = groupsize; - int ae, he, e, f, r; - bool a; + int ascii_len, hex_len, expected_len, fill_point, ngroups, rc; + bool match; total_tests++; memset(buf, FILL_CHAR, sizeof(buf)); - r = hex_dump_to_buffer(data_b, len, rs, gs, buf, buflen, ascii); + rc = hex_dump_to_buffer(data_b, len, rowsize, groupsize, buf, buflen, ascii); /* * Caller must provide the data length multiple of groupsize. The * calculations below are made with that assumption in mind. */ - ae = rs * 2 /* hex */ + rs / gs /* spaces */ + 1 /* space */ + len /* ascii */; - he = (gs * 2 /* hex */ + 1 /* space */) * len / gs - 1 /* no trailing space */; + ngroups = rowsize / groupsize; + hex_len = (groupsize * 2 /* hex */ + 1 /* spaces */) * ngroups + - 1 /* no trailing space */; + ascii_len = hex_len + 2 /* space */ + len /* ascii */; + + if (len < rowsize) { + ngroups = len / groupsize; + hex_len = (groupsize * 2 /* hex */ + 1 /* spaces */) * ngroups + - 1 /* no trailing space */; + } - if (ascii) - e = ae; - else - e = he; + expected_len = (ascii) ? ascii_len : hex_len; - f = min_t(int, e + 1, buflen); + fill_point = min_t(int, expected_len + 1, buflen); if (buflen) { - test_hexdump_prepare_test(len, rs, gs, test, sizeof(test), ascii); - test[f - 1] = '\0'; + test_hexdump_prepare_test(len, rowsize, groupsize, test, + sizeof(test), ascii); + test[fill_point - 1] = '\0'; } - memset(test + f, FILL_CHAR, sizeof(test) - f); + memset(test + fill_point, FILL_CHAR, sizeof(test) - fill_point); - a = r == e && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE); + match = rc == expected_len && !memcmp(test, buf, TEST_HEXDUMP_BUF_SIZE); buf[sizeof(buf) - 1] = '\0'; - if (!a) { - pr_err("Len: %zu buflen: %zu strlen: %zu\n", - len, buflen, strnlen(buf, sizeof(buf))); - pr_err("Result: %d '%s'\n", r, buf); - pr_err("Expect: %d '%s'\n", e, test); + if (!match) { + pr_err("rowsize: %u groupsize: %u ascii: %d Len: %zu buflen: %zu strlen: %zu\n", + rowsize, groupsize, ascii, len, buflen, + strnlen(buf, sizeof(buf))); + pr_err("Result: %d '%-.*s'\n", rc, (int)buflen, buf); + pr_err("Expect: %d '%-.*s'\n", expected_len, (int)buflen, test); failed_tests++; + } } -- 2.21.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 4/7] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva In order to support additional features in hex_dump_to_buffer, replace the ascii bool parameter with flags. Signed-off-by: Alastair D'Silva --- drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 6 -- drivers/mailbox/mailbox-test.c| 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 3 ++- drivers/net/wireless/intel/iwlegacy/3945-mac.c| 2 +- drivers/platform/chrome/wilco_ec/debugfs.c| 2 +- drivers/scsi/scsi_logging.c | 8 +++- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 3 ++- include/linux/printk.h| 8 lib/hexdump.c | 15 --- lib/test_hexdump.c| 5 +++-- 14 files changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 49fa43ff02ba..fb133e729f9a 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1318,7 +1318,7 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len) WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, rowsize, sizeof(u32), line, sizeof(line), - false) >= sizeof(line)); + 0) >= sizeof(line)); drm_printf(m, "[%04zx] %s\n", pos, line); prev = buf + pos; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index 386731ec2489..f13f34db6c17 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -84,7 +84,8 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) while (l < (int)len) { hex_dump_to_buffer(msg + l, len - l, 32, 1, - isar->log, 256, 1); + isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; @@ -113,7 +114,8 @@ rcv_mbox(struct isar_hw *isar, u8 *msg) while (l < (int)isar->clsb) { hex_dump_to_buffer(msg + l, isar->clsb - l, 32, - 1, isar->log, 256, 1); + 1, isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c index 4e4ac4be6423..2f9a094d0259 100644 --- a/drivers/mailbox/mailbox-test.c +++ b/drivers/mailbox/mailbox-test.c @@ -213,7 +213,7 @@ static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf, hex_dump_to_buffer(ptr, MBOX_BYTES_PER_LINE, MBOX_BYTES_PER_LINE, 1, touser + l, - MBOX_HEXDUMP_LINE_LEN, true); + MBOX_HEXDUMP_LINE_LEN, HEXDUMP_ASCII); ptr += MBOX_BYTES_PER_LINE; l += MBOX_HEXDUMP_LINE_LEN; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 0cc911f928b1..e954a31cee0c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -2992,7 +2992,7 @@ void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) unsigned int len = min(skb->len - i, 32U); hex_dump_to_buffer(>data[i], len, 32, 1, - buffer, sizeof(buffer), false); + buffer, sizeof(buffer), 0); netdev_dbg(netdev, " %#06x: %s\n", i, buffer); } diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c index eb1c6b03c329..b80adfa1f890 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c @@ -349,7 +349,7 @@ void xlgmac_
[PATCH v2 7/7] lib/hexdump.c: Optionally retain byte ordering
From: Alastair D'Silva The behaviour of hexdump groups is to print the data out as if it was a native-endian number. This patch tweaks the documentation to make this clear, and also adds the HEXDUMP_RETAIN_BYTE_ORDER flag to allow groups of multiple bytes to be printed without affecting the ordering of the printed bytes. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 1 + lib/hexdump.c | 30 + lib/test_hexdump.c | 60 +- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 5231a14e4593..15277d50159c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -488,6 +488,7 @@ enum { #define HEXDUMP_2_GRP_SPACES (1 << 5) #define HEXDUMP_4_GRP_SPACES (1 << 6) #define HEXDUMP_8_GRP_SPACES (1 << 7) +#define HEXDUMP_RETAIN_BYTE_ORDER (1 << 8) extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index febd614406d1..bfc9800630ae 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -127,7 +127,8 @@ static void separator_parameters(u64 flags, int groupsize, int *sep_chars, * @buf: data blob to dump * @len: number of bytes in the @buf * @rowsize: number of bytes to print per line; must be a multiple of groupsize - * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1) + * @groupsize: number of bytes to convert to a native endian number and print: + *1, 2, 4, 8; default = 1 * @linebuf: where to put the converted data * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: @@ -138,6 +139,9 @@ static void separator_parameters(u64 flags, int groupsize, int *sep_chars, * HEXDUMP_2_GRP_SPACES: insert a ' ' after every 2 groups * HEXDUMP_4_GRP_SPACES: insert a ' ' after every 4 groups * HEXDUMP_8_GRP_SPACES: insert a ' ' after every 8 groups + * HEXDUMP_RETAIN_BYTE_ORDER: Retain the byte ordering of groups + * instead of treating each group as a + * native-endian number * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -171,6 +175,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int ret; int sep_chars = 0; char sep = 0; + bool big_endian = (flags & HEXDUMP_RETAIN_BYTE_ORDER) ? 1 : 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -202,10 +207,13 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, const u64 *ptr8 = buf; for (j = 0; j < ngroups; j++) { + u64 val = big_endian ? + be64_to_cpu(get_unaligned(ptr8 + j)) : + get_unaligned(ptr8 + j); ret = snprintf(linebuf + lx, linebuflen - lx, "%s%16.16llx", j ? group_separator(j, flags) : "", - get_unaligned(ptr8 + j)); + val); if (ret >= linebuflen - lx) goto overflow1; lx += ret; @@ -214,10 +222,14 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, const u32 *ptr4 = buf; for (j = 0; j < ngroups; j++) { + u32 val = big_endian ? + be32_to_cpu(get_unaligned(ptr4 + j)) : + get_unaligned(ptr4 + j); + ret = snprintf(linebuf + lx, linebuflen - lx, "%s%8.8x", j ? group_separator(j, flags) : "", - get_unaligned(ptr4 + j)); + val); if (ret >= linebuflen - lx) goto overflow1; lx += ret; @@ -226,10 +238,14 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, const u16 *ptr2 = buf; for (j = 0; j < ngroups; j++) { + u16 val = big_endian ? + be16_to_cpu(get_unaligned(ptr2 + j)) : + get_unaligned(ptr2 + j); +
[PATCH v2 2/7] lib/hexdump.c: Relax rowsize checks in hex_dump_to_buffer
From: Alastair D'Silva This patch removes the hardcoded row limits and allows for other lengths. These lengths must still be a multiple of groupsize. This allows structs that are not 16/32 bytes to display on a single line. This patch also expands the self-tests to test row sizes up to 64 bytes (though they can now be arbitrarily long). Signed-off-by: Alastair D'Silva --- lib/hexdump.c | 48 -- lib/test_hexdump.c | 52 ++ 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/lib/hexdump.c b/lib/hexdump.c index 81b70ed37209..3943507bc0e9 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -12,6 +12,7 @@ #include #include #include +#include #include const char hex_asc[] = "0123456789abcdef"; @@ -80,14 +81,15 @@ EXPORT_SYMBOL(bin2hex); * 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 + * @rowsize: number of bytes to print per line; must be a multiple of groupsize * @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. + * hex_dump_to_buffer() works on one "line" of output at a time, converting + * bytes of input to hexadecimal (and optionally printable ASCII) + * until bytes have been emitted. * * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data * to a hex + ASCII dump at the supplied memory location. @@ -116,16 +118,17 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, 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; + if (rowsize % groupsize) + rowsize -= rowsize % groupsize; + + if (len > rowsize) /* limit to one line at a time */ + len = rowsize; + ngroups = len / groupsize; ascii_column = rowsize * 2 + rowsize / groupsize + 1; @@ -216,7 +219,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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 + * @rowsize: number of bytes to print per line; must be a multiple of groupsize * @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 @@ -226,10 +229,9 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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. + * lines of rowsize/groupsize groups of input data converted to hex + + * (optionally) ASCII output. * * E.g.: * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, @@ -246,17 +248,29 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, { const u8 *ptr = buf; int i, linelen, remaining = len; - unsigned char linebuf[32 * 3 + 2 + 32 + 1]; + unsigned char *linebuf; + unsigned int linebuf_len; - if (rowsize != 16 && rowsize != 32) - rowsize = 16; + if (rowsize % groupsize) + rowsize -= rowsize % groupsize; + + /* Worst case line length: +* 2 hex chars + space per byte in, 2 spaces, 1 char per byte in, NULL +*/ + linebuf_len = rowsize * 3 + 2 + rowsize + 1; + linebuf = kzalloc(linebuf_len, GFP_KERNEL); + if (!linebuf) { + printk("%s%shexdump: Could not alloc %u bytes for buffer\n", + level, prefix_str, linebuf_len); + return; + } for (i = 0; i < len; i += rowsize) { linelen = min(remaining, rowsize); remaining -= rowsize; hex_dump_to_buf
[PATCH v2 5/7] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva With the wider display format, it can become hard to identify how many bytes into the line you are looking at. The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to print vertical lines to separate every N groups of bytes. eg. buf:: 454d414e 43415053|4e495f45 00584544 NAMESPAC|E_INDEX. buf:0010: 0002| | Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 +++ lib/hexdump.c | 59 -- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 00a82e468643..dc693aec394c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -482,6 +482,9 @@ enum { #define HEXDUMP_ASCII (1 << 0) #define HEXDUMP_SUPPRESS_REPEATED (1 << 1) +#define HEXDUMP_2_GRP_LINES(1 << 2) +#define HEXDUMP_4_GRP_LINES(1 << 3) +#define HEXDUMP_8_GRP_LINES(1 << 4) extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, diff --git a/lib/hexdump.c b/lib/hexdump.c index ddd1697e5f9b..6f4d1176c332 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -77,6 +77,23 @@ char *bin2hex(char *dst, const void *src, size_t count) } EXPORT_SYMBOL(bin2hex); +static const char *group_separator(int group, u64 flags) +{ + if (group == 0) + return " "; + + if ((flags & HEXDUMP_8_GRP_LINES) && !((group) % 8)) + return "|"; + + if ((flags & HEXDUMP_4_GRP_LINES) && !((group) % 4)) + return "|"; + + if ((flags & HEXDUMP_2_GRP_LINES) && !((group) % 2)) + return "|"; + + return " "; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -87,6 +104,9 @@ EXPORT_SYMBOL(bin2hex); * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: * HEXDUMP_ASCII: include ASCII after the hex output + * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups + * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups + * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, converting * bytes of input to hexadecimal (and optionally printable ASCII) @@ -118,6 +138,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int j, lx = 0; int ascii_column; int ret; + int line_chars = 0; if (!is_power_of_2(groupsize) || groupsize > 8) groupsize = 1; @@ -144,7 +165,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%16.16llx", j ? " " : "", + "%s%16.16llx", + j ? group_separator(j, flags) : "", get_unaligned(ptr8 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -155,7 +177,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%8.8x", j ? " " : "", + "%s%8.8x", + j ? group_separator(j, flags) : "", get_unaligned(ptr4 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -166,7 +189,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%4.4x", j ? " " : "", + "%s%4.4x", + j ? group_separator(j, flags) : "", get_unaligned(ptr2 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -196,11 +220,26 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int gr
RE: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
> -Original Message- > From: David Laight > Sent: Monday, 15 April 2019 8:21 PM > To: 'Alastair D'Silva' ; 'Petr Mladek' > > Cc: 'Alastair D'Silva' ; 'Jani Nikula' > ; 'Joonas Lahtinen' > ; 'Rodrigo Vivi' ; > 'David Airlie' ; 'Daniel Vetter' ; 'Karsten > Keil' ; 'Jassi Brar' ; 'Tom > Lendacky' ; 'David S. Miller' > ; 'Jose Abreu' ; 'Kalle > Valo' ; 'Stanislaw Gruszka' ; > 'Benson Leung' ; 'Enric Balletbo i Serra' > ; 'James E.J. Bottomley' > ; 'Martin K. Petersen' ; > 'Greg Kroah-Hartman' ; 'Alexander Viro' > ; 'Sergey Senozhatsky' > ; 'Steven Rostedt' > ; 'Andrew Morton' ; > intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: RE: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in > hex_dump_to_buffer with flags > > From: Alastair D'Silva > > Sent: 15 April 2019 11:07 > ... > > In the above example the author only wants the hex output, while in > > other situations, both hex & ASCII output is desirable. If you just > > want ASCII output, the caller should just use a printk or one of it's > wrappers. > > Hexdump will 'sanitise' the ASCII. > This is functionality that doesn't exist in the current hexdump implementation (you always get the hex version). I think a better option would be to factor out the sanitisation and expose that as a separate function. > Although I think you'd want a 'no hex' flag to suppress the hex. > > Probably more useful flags are ones to suppress the address column. This is already supported by the prefix_type parameter - are you proposing that we eliminate the parameter & combine it with flags? > I've also used flags to enable (or disable) suppression of multiple lines of > zeros of constant bytes. > In that case you may want hexdump to return the flags for the next call when > a large buffer is being dumped in fragments. I'm afraid I don't quite follow here, hex_dump_to_buffer doesn't alter the flags, so the caller already knows it. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 1/4] lib/hexdump.c: Allow 64 bytes per line
> From: Alastair D'Silva > > Sent: 15 April 2019 11:29 > ... > > I do, and I believe the choice of the output length should be in the > > hands of the caller. > > > > On further thought, it would make more sense to remove the hardcoded > > list of sizes and just enforce a power of 2. The function shouldn't > > dictate what the caller can and can't do beyond the technical limits of it's > implementation. > > Why powers of two? > You may want the length to match sizeof (struct foo). > You might even want the address increment to be larger that the number of > lines dumped. Good point, the base requirement is that it should be a multiple of groupsize. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 1/4] lib/hexdump.c: Allow 64 bytes per line
> > > On Wed 2019-04-10 13:17:17, Alastair D'Silva wrote: > > > > From: Alastair D'Silva > > > > > > > > With modern high resolution screens, we can display more data, > > > > which makes life a bit easier when debugging. > > > > > > I have quite some doubts about this feature. > > > > > > We are talking about more than 256 characters per-line. I wonder if > > > such a long line is really easier to read for a human. > > > > It's basically 2 separate panes of information side by side, the > > hexdump and the ASCII version. > > > > I'm using this myself when dealing with the pmem labels, and it works > > quite nicely. > > I am sure that it works for you. But I do not believe that it would be useful in > general. I do, and I believe the choice of the output length should be in the hands of the caller. On further thought, it would make more sense to remove the hardcoded list of sizes and just enforce a power of 2. The function shouldn't dictate what the caller can and can't do beyond the technical limits of it's implementation. Other print/debug functions don't restrict the output size, and I can't see a good justification why hexdump should either. > > > I am not expert but there is a reason why the standard is 80 > > > characters > > per- > > > line. I guess that anything above 100 characters is questionable. > > > https://en.wikipedia.org/wiki/Line_length > > > somehow confirms that. > > > > > > Second, if we take 8 pixels per-character. Then we need > > > 2048 to show the 256 characters. It is more than HD. > > > IMHO, there is still huge number of people that even do not have HD > > display, > > > especially on a notebook. > > > > The intent is to make debugging easier when dealing with large chunks > > of binary data. I don't expect end users to see this output. > > How is it supposed to be used then? Only by your temporary patches? Let me rephrase that, I don't expect end users to *use* this data. Current usage of the hexdump functions are predominantly centred around logging and debugging, and clearly targeted at someone intimately familiar with the relevant subsystem. I expect future use would be similar. Debugging may be as part of active development, or from a log supplied from an end user. In either case, it should be up to the author (as a representative for the consumers of the data) to decide how it should be formatted. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
> -Original Message- > From: David Laight > Sent: Monday, 15 April 2019 9:04 PM > To: 'Alastair D'Silva' ; 'Petr Mladek' > > Cc: 'Alastair D'Silva' ; 'Jani Nikula' > ; 'Joonas Lahtinen' > ; 'Rodrigo Vivi' ; > 'David Airlie' ; 'Daniel Vetter' ; 'Karsten > Keil' ; 'Jassi Brar' ; 'Tom > Lendacky' ; 'David S. Miller' > ; 'Jose Abreu' ; 'Kalle > Valo' ; 'Stanislaw Gruszka' ; > 'Benson Leung' ; 'Enric Balletbo i Serra' > ; 'James E.J. Bottomley' > ; 'Martin K. Petersen' ; > 'Greg Kroah-Hartman' ; 'Alexander Viro' > ; 'Sergey Senozhatsky' > ; 'Steven Rostedt' > ; 'Andrew Morton' ; > intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: RE: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in > hex_dump_to_buffer with flags > > From: Alastair D'Silva > > Sent: 15 April 2019 11:45 > ... > > > Although I think you'd want a 'no hex' flag to suppress the hex. > > > > > > Probably more useful flags are ones to suppress the address column. > > > > This is already supported by the prefix_type parameter - are you > > proposing that we eliminate the parameter & combine it with flags? > > I was looking at the flags on one of my hexdump() functions... > > > > I've also used flags to enable (or disable) suppression of multiple > > > lines of zeros of constant bytes. > > > In that case you may want hexdump to return the flags for the next > > > call when a large buffer is being dumped in fragments. > > > > I'm afraid I don't quite follow here, hex_dump_to_buffer doesn't alter > > the flags, so the caller already knows it. > > If you are suppressing lines of zeros and dumping a buffer in several blocks > then subsequent calls need to know that the last line of the previous call was > suppressed zeros - and carry on with the same suppressed block. Why wouldn't you do this with a single call to print_hex_dump? (that is where the repeated lines are suppressed) That will already take chunks of the buffer until the whole thing is output, in what situation do you see a caller chunking the access themselves? -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes
> > > On Wed 2019-04-10 13:17:18, Alastair D'Silva wrote: > > > > From: Alastair D'Silva > > > > > > > > Some buffers may only be partially filled with useful data, while > > > > the rest is padded (typically with 0x00 or 0xff). > > > > > > > > This patch introduces flags which allow lines of padding bytes to > > > > be suppressed, making the output easier to interpret: > > > > HEXDUMP_SUPPRESS_0X00, HEXDUMP_SUPPRESS_0XFF > > > > > > > > The first and last lines are not suppressed by default, so the > > > > function always outputs something. This behaviour can be further > > > > controlled with the HEXDUMP_SUPPRESS_FIRST & > > > HEXDUMP_SUPPRESS_LAST flags. > > > > > > > > An inline wrapper function is provided for backwards compatibility > > > > with existing code, which maintains the original behaviour. > > > > > > > > > > > diff --git a/lib/hexdump.c b/lib/hexdump.c index > > > > b8a164814744..2f3bafb55a44 100644 > > > > --- a/lib/hexdump.c > > > > +++ b/lib/hexdump.c > > > > +void print_hex_dump_ext(const char *level, const char *prefix_str, > > > > + int prefix_type, int rowsize, int groupsize, > > > > + const void *buf, size_t len, u64 flags) > > > > { > > > > const u8 *ptr = buf; > > > > - int i, linelen, remaining = len; > > > > + int i, remaining = len; > > > > unsigned char linebuf[64 * 3 + 2 + 64 + 1]; > > > > + bool first_line = true; > > > > > > > > if (rowsize != 16 && rowsize != 32 && rowsize != 64) > > > > rowsize = 16; > > > > > > > > for (i = 0; i < len; i += rowsize) { > > > > - linelen = min(remaining, rowsize); > > > > + bool skip = false; > > > > + int linelen = min(remaining, rowsize); > > > > + > > > > remaining -= rowsize; > > > > > > > > + if (flags & HEXDUMP_SUPPRESS_0X00) > > > > + skip = buf_is_all(ptr + i, linelen, 0x00); > > > > + > > > > + if (!skip && (flags & HEXDUMP_SUPPRESS_0XFF)) > > > > + skip = buf_is_all(ptr + i, linelen, 0xff); > > > > + > > > > + if (first_line && !(flags & HEXDUMP_SUPPRESS_FIRST)) > > > > + skip = false; > > > > + > > > > + if (remaining <= 0 && !(flags & HEXDUMP_SUPPRESS_LAST)) > > > > + skip = false; > > > > + > > > > + if (skip) > > > > + continue; > > > > > > IMHO, quietly skipping lines could cause a lot of confusion, > > > espcially > > when the address is not printed. > > > > > It's up to the caller to decide how they want it displayed. > > I wonder who would want to quietly skip some data values. > Are you using it yourself? Could you please provide an example? Yes, but I don't have the content with me at the moment, so I can't share it. I'm dumping persistent memory labels, which are 64kB long, but only the first few hundred bytes are populated. > I do not see why we would need to complicate the API and code by this. > > The behavior proposed by Tvrtko Ursulin makes much more sense. I mean > https://lkml.kernel.org/r/929244ed-cc7f-b0f3-b5ac- > 50e798e83...@linux.intel.com I agree that is better, I'll add that to V2. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
> -Original Message- > From: Petr Mladek > Sent: Monday, 15 April 2019 7:24 PM > To: Alastair D'Silva > Cc: 'Alastair D'Silva' ; 'Jani Nikula' > ; 'Joonas Lahtinen' > ; 'Rodrigo Vivi' ; > 'David Airlie' ; 'Daniel Vetter' ; 'Karsten > Keil' ; 'Jassi Brar' ; 'Tom > Lendacky' ; 'David S. Miller' > ; 'Jose Abreu' ; 'Kalle > Valo' ; 'Stanislaw Gruszka' ; > 'Benson Leung' ; 'Enric Balletbo i Serra' > ; 'James E.J. Bottomley' > ; 'Martin K. Petersen' ; > 'Greg Kroah-Hartman' ; 'Alexander Viro' > ; 'Sergey Senozhatsky' > ; 'Steven Rostedt' > ; 'Andrew Morton' ; > intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: Re: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in > hex_dump_to_buffer with flags > > On Sat 2019-04-13 09:31:27, Alastair D'Silva wrote: > > > -Original Message----- > > > From: Petr Mladek > > > Sent: Saturday, 13 April 2019 12:12 AM > > > To: Alastair D'Silva > > > Cc: alast...@d-silva.org; Jani Nikula ; > > Joonas > > > Lahtinen ; Rodrigo Vivi > > > ; David Airlie ; Daniel > > > Vetter ; Karsten Keil ; Jassi > > > Brar ; Tom Lendacky > > > ; David S. Miller > ; > > > Jose Abreu ; Kalle Valo > > > ; Stanislaw Gruszka ; > > > Benson Leung ; Enric Balletbo i Serra > > > ; James E.J. Bottomley > > > ; Martin K. Petersen > > > ; Greg Kroah-Hartman > > > ; Alexander Viro > > > ; Sergey Senozhatsky > > > ; Steven Rostedt > > > ; Andrew Morton foundation.org>; > > > intel- g...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; > > > linux- ker...@vger.kernel.org; net...@vger.kernel.org; > > > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > > > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > > > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > > > Subject: Re: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in > > > hex_dump_to_buffer with flags > > > > > > On Wed 2019-04-10 13:17:19, Alastair D'Silva wrote: > > > > From: Alastair D'Silva > > > > > > > > In order to support additional features in hex_dump_to_buffer, > > > > replace the ascii bool parameter with flags. > > > > > > > > Signed-off-by: Alastair D'Silva > > > > --- > > > > drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- > > > > drivers/isdn/hardware/mISDN/mISDNisar.c | 6 -- > > > > drivers/mailbox/mailbox-test.c| 2 +- > > > > drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- > > > > drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- > > > > drivers/net/wireless/ath/ath10k/debug.c | 3 ++- > > > > drivers/net/wireless/intel/iwlegacy/3945-mac.c| 2 +- > > > > drivers/platform/chrome/wilco_ec/debugfs.c| 3 ++- > > > > drivers/scsi/scsi_logging.c | 8 +++- > > > > drivers/staging/fbtft/fbtft-core.c| 2 +- > > > > fs/seq_file.c | 3 ++- > > > > include/linux/printk.h| 2 +- > > > > lib/hexdump.c | 15 --- > > > > lib/test_hexdump.c| 5 +++-- > > > > 14 files changed, 31 insertions(+), 26 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c > > > > b/drivers/gpu/drm/i915/intel_engine_cs.c > > > > index 49fa43ff02ba..fb133e729f9a 100644 > > > > --- a/drivers/gpu/drm/i915/intel_engine_cs.c > > > > +++ b/drivers/gpu/drm/i915/intel_engine_cs.c > > > > @@ -1318,7 +1318,7 @@ static void hexdump(struct drm_printer *m, > > > > const > > > void *buf, size_t len) > > > > WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - > > > pos, > > > > rowsize, sizeof(u32), > > > > line, sizeof(line), > > > > - false) >= sizeof(line)); > > > > + 0) >= sizeof(line))
RE: [PATCH 1/4] lib/hexdump.c: Allow 64 bytes per line
> -Original Message- > From: Petr Mladek > Sent: Friday, 12 April 2019 11:48 PM > To: Alastair D'Silva > Cc: alast...@d-silva.org; Jani Nikula ; Joonas > Lahtinen ; Rodrigo Vivi > ; David Airlie ; Daniel Vetter > ; Karsten Keil ; Jassi Brar > ; Tom Lendacky ; > David S. Miller ; Jose Abreu > ; Kalle Valo ; > Stanislaw Gruszka ; Benson Leung > ; Enric Balletbo i Serra > ; James E.J. Bottomley > ; Martin K. Petersen ; > Greg Kroah-Hartman ; Alexander Viro > ; Sergey Senozhatsky > ; Steven Rostedt ; > Andrew Morton ; intel- > g...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: Re: [PATCH 1/4] lib/hexdump.c: Allow 64 bytes per line > > On Wed 2019-04-10 13:17:17, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > With modern high resolution screens, we can display more data, which > > makes life a bit easier when debugging. > > I have quite some doubts about this feature. > > We are talking about more than 256 characters per-line. I wonder if such a > long line is really easier to read for a human. It's basically 2 separate panes of information side by side, the hexdump and the ASCII version. I'm using this myself when dealing with the pmem labels, and it works quite nicely. > > I am not expert but there is a reason why the standard is 80 characters per- > line. I guess that anything above 100 characters is questionable. > https://en.wikipedia.org/wiki/Line_length > somehow confirms that. > > Second, if we take 8 pixels per-character. Then we need > 2048 to show the 256 characters. It is more than HD. > IMHO, there is still huge number of people that even do not have HD display, > especially on a notebook. The intent is to make debugging easier when dealing with large chunks of binary data. I don't expect end users to see this output. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
> -Original Message- > From: Petr Mladek > Sent: Saturday, 13 April 2019 12:12 AM > To: Alastair D'Silva > Cc: alast...@d-silva.org; Jani Nikula ; Joonas > Lahtinen ; Rodrigo Vivi > ; David Airlie ; Daniel Vetter > ; Karsten Keil ; Jassi Brar > ; Tom Lendacky ; > David S. Miller ; Jose Abreu > ; Kalle Valo ; > Stanislaw Gruszka ; Benson Leung > ; Enric Balletbo i Serra > ; James E.J. Bottomley > ; Martin K. Petersen ; > Greg Kroah-Hartman ; Alexander Viro > ; Sergey Senozhatsky > ; Steven Rostedt ; > Andrew Morton ; intel- > g...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: Re: [PATCH 3/4] lib/hexdump.c: Replace ascii bool in > hex_dump_to_buffer with flags > > On Wed 2019-04-10 13:17:19, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > In order to support additional features in hex_dump_to_buffer, replace > > the ascii bool parameter with flags. > > > > Signed-off-by: Alastair D'Silva > > --- > > drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- > > drivers/isdn/hardware/mISDN/mISDNisar.c | 6 -- > > drivers/mailbox/mailbox-test.c| 2 +- > > drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- > > drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- > > drivers/net/wireless/ath/ath10k/debug.c | 3 ++- > > drivers/net/wireless/intel/iwlegacy/3945-mac.c| 2 +- > > drivers/platform/chrome/wilco_ec/debugfs.c| 3 ++- > > drivers/scsi/scsi_logging.c | 8 +++- > > drivers/staging/fbtft/fbtft-core.c| 2 +- > > fs/seq_file.c | 3 ++- > > include/linux/printk.h| 2 +- > > lib/hexdump.c | 15 --- > > lib/test_hexdump.c| 5 +++-- > > 14 files changed, 31 insertions(+), 26 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c > > b/drivers/gpu/drm/i915/intel_engine_cs.c > > index 49fa43ff02ba..fb133e729f9a 100644 > > --- a/drivers/gpu/drm/i915/intel_engine_cs.c > > +++ b/drivers/gpu/drm/i915/intel_engine_cs.c > > @@ -1318,7 +1318,7 @@ static void hexdump(struct drm_printer *m, const > void *buf, size_t len) > > WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - > pos, > > rowsize, sizeof(u32), > > line, sizeof(line), > > - false) >= sizeof(line)); > > + 0) >= sizeof(line)); > > It might be more clear when we define: > > #define HEXDUMP_BINARY 0 This feels unnecessary, and weird. Omitting the flag won't disable the hex output (as expected), and if you don't want hex output, why call hexdump in the first place? > > drm_printf(m, "[%04zx] %s\n", pos, line); > > > > prev = buf + pos; > > diff --git a/include/linux/printk.h b/include/linux/printk.h index > > c014e5573665..82975853c400 100644 > > --- a/include/linux/printk.h > > +++ b/include/linux/printk.h > > @@ -493,7 +493,7 @@ enum { > > > > extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, > > int groupsize, char *linebuf, size_t linebuflen, > > - bool ascii); > > + u64 flags); > > I wonder how fancy hex_dump could be. IMHO, u32 should be enough. > The last famous words ;-) > > Best Regards, > Petr > > > --- > This email has been checked for viruses by AVG. > https://www.avg.com ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes
> -Original Message- > From: Petr Mladek > Sent: Saturday, 13 April 2019 12:04 AM > To: Alastair D'Silva > Cc: alast...@d-silva.org; Jani Nikula ; Joonas > Lahtinen ; Rodrigo Vivi > ; David Airlie ; Daniel Vetter > ; Karsten Keil ; Jassi Brar > ; Tom Lendacky ; > David S. Miller ; Jose Abreu > ; Kalle Valo ; > Stanislaw Gruszka ; Benson Leung > ; Enric Balletbo i Serra > ; James E.J. Bottomley > ; Martin K. Petersen ; > Greg Kroah-Hartman ; Alexander Viro > ; Sergey Senozhatsky > ; Steven Rostedt ; > Andrew Morton ; intel- > g...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: Re: [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler > bytes > > On Wed 2019-04-10 13:17:18, Alastair D'Silva wrote: > > From: Alastair D'Silva > > > > Some buffers may only be partially filled with useful data, while the > > rest is padded (typically with 0x00 or 0xff). > > > > This patch introduces flags which allow lines of padding bytes to be > > suppressed, making the output easier to interpret: > > HEXDUMP_SUPPRESS_0X00, HEXDUMP_SUPPRESS_0XFF > > > > The first and last lines are not suppressed by default, so the > > function always outputs something. This behaviour can be further > > controlled with the HEXDUMP_SUPPRESS_FIRST & > HEXDUMP_SUPPRESS_LAST flags. > > > > An inline wrapper function is provided for backwards compatibility > > with existing code, which maintains the original behaviour. > > > > > diff --git a/lib/hexdump.c b/lib/hexdump.c index > > b8a164814744..2f3bafb55a44 100644 > > --- a/lib/hexdump.c > > +++ b/lib/hexdump.c > > +void print_hex_dump_ext(const char *level, const char *prefix_str, > > + int prefix_type, int rowsize, int groupsize, > > + const void *buf, size_t len, u64 flags) > > { > > const u8 *ptr = buf; > > - int i, linelen, remaining = len; > > + int i, remaining = len; > > unsigned char linebuf[64 * 3 + 2 + 64 + 1]; > > + bool first_line = true; > > > > if (rowsize != 16 && rowsize != 32 && rowsize != 64) > > rowsize = 16; > > > > for (i = 0; i < len; i += rowsize) { > > - linelen = min(remaining, rowsize); > > + bool skip = false; > > + int linelen = min(remaining, rowsize); > > + > > remaining -= rowsize; > > > > + if (flags & HEXDUMP_SUPPRESS_0X00) > > + skip = buf_is_all(ptr + i, linelen, 0x00); > > + > > + if (!skip && (flags & HEXDUMP_SUPPRESS_0XFF)) > > + skip = buf_is_all(ptr + i, linelen, 0xff); > > + > > + if (first_line && !(flags & HEXDUMP_SUPPRESS_FIRST)) > > + skip = false; > > + > > + if (remaining <= 0 && !(flags & HEXDUMP_SUPPRESS_LAST)) > > + skip = false; > > + > > + if (skip) > > + continue; > > IMHO, quietly skipping lines could cause a lot of confusion, espcially when > the address is not printed. > It's up to the caller to decide how they want it displayed. > I wonder how it would look like when we print something like: > > --- skipped XX lines full of 0x00 --- This could be added as a later enhancement, with a new flag (eg. HEXDUMP_SUPPRESS_VERBOSE). > > Then we might even remove the SUPPRESS_FIRST, SUPPRESS_LAST and the > ambiguous QUIET flags. > > > + > > + first_line = false; > > This should be above the if (skip). > > > + > > hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, > > - linebuf, sizeof(linebuf), ascii); > > + linebuf, sizeof(linebuf), > > + flags & HEXDUMP_ASCII); > > > > switch (prefix_type) { > > case DUMP_PREFIX_ADDRESS: > > @@ -272,7 +316,7 @@ void print_hex_dump(const char *level, const char > *prefix_str, int prefix_type, > > } > > } > > } > > -EXPORT_SYMBOL(print_hex_dump); > > +EXPORT_SYMBOL(print_hex_dump_ext); > > We should still export even the original function that is still used everywhere. It's replaced with an inline wrapper function, there's no need to export it. -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva msn: alast...@d-silva.org blog: http://alastair.d-silva.orgTwitter: @EvilDeece ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
> -Original Message- > From: David Laight > Sent: Wednesday, 10 April 2019 6:45 PM > To: 'Alastair D'Silva' ; alast...@d-silva.org > Cc: Jani Nikula ; Joonas Lahtinen > ; Rodrigo Vivi ; > David Airlie ; Daniel Vetter ; Karsten Keil > ; Jassi Brar ; Tom Lendacky > ; David S. Miller ; > Jose Abreu ; Kalle Valo > ; Stanislaw Gruszka ; > Benson Leung ; Enric Balletbo i Serra > ; James E.J. Bottomley > ; Martin K. Petersen ; > Greg Kroah-Hartman ; Alexander Viro > ; Petr Mladek ; Sergey > Senozhatsky ; Steven Rostedt > ; Andrew Morton ; > intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux- > ker...@vger.kernel.org; net...@vger.kernel.org; > ath...@lists.infradead.org; linux-wirel...@vger.kernel.org; linux- > s...@vger.kernel.org; linux-fb...@vger.kernel.org; > de...@driverdev.osuosl.org; linux-fsde...@vger.kernel.org > Subject: RE: [PATCH 4/4] lib/hexdump.c: Allow multiple groups to be > separated by lines '|' > > From: Alastair D'Silva > > Sent: 10 April 2019 04:17 > > With the wider display format, it can become hard to identify how many > > bytes into the line you are looking at. > > > > The patch adds new flags to hex_dump_to_buffer() and > print_hex_dump() > > to print vertical lines to separate every N groups of bytes. > > > > eg. > > buf:: 454d414e 43415053|4e495f45 00584544 > NAMESPAC|E_INDEX. > > buf:0010: 0002| | > > Ugg, that is just horrid. > It is enough to add an extra space if you really need the columns to be more > easily counted. > I did consider that, but it would be a more invasive change, as the buffer length required would differ based on the flags. > I'm not even sure that is needed if you are printing 32bit words. > OTOH 32bit words makes 64bit values really stupid on LE systems. > Bytes with extra spaces every 4 bytes is the format I prefer even for long > lines. > > Oh, and if you are using hexdump() a lot you want a version that never uses > snprintf(). > > David > > - > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, > MK1 1PT, UK Registration No: 1397386 (Wales) > > > --- > This email has been checked for viruses by AVG. > https://www.avg.com ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/4] Hexdump enhancements
From: Alastair D'Silva Apologies for the large CC list, it's a heads up for those responsible for subsystems where a prototype change in generic code causes a change in those subsystems. This series enhances hexdump. These improve the readability of the dumped data in certain situations (eg. wide terminals are available, many lines of empty bytes exist, etc). The default behaviour of hexdump is unchanged, however, the prototype for hex_dump_to_buffer() has changed, and print_hex_dump() has been renamed to print_hex_dump_ext(), with a wrapper replacing it for compatibility with existing code, which would have been too invasive to change. Alastair D'Silva (4): lib/hexdump.c: Allow 64 bytes per line lib/hexdump.c: Optionally suppress lines of filler bytes lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags lib/hexdump.c: Allow multiple groups to be separated by lines '|' drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 6 +- drivers/mailbox/mailbox-test.c| 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 3 +- .../net/wireless/intel/iwlegacy/3945-mac.c| 2 +- drivers/platform/chrome/wilco_ec/debugfs.c| 3 +- drivers/scsi/scsi_logging.c | 8 +- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 3 +- include/linux/printk.h| 38 - lib/hexdump.c | 143 ++ lib/test_hexdump.c| 5 +- 14 files changed, 168 insertions(+), 53 deletions(-) -- 2.20.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes
From: Alastair D'Silva Some buffers may only be partially filled with useful data, while the rest is padded (typically with 0x00 or 0xff). This patch introduces flags which allow lines of padding bytes to be suppressed, making the output easier to interpret: HEXDUMP_SUPPRESS_0X00, HEXDUMP_SUPPRESS_0XFF The first and last lines are not suppressed by default, so the function always outputs something. This behaviour can be further controlled with the HEXDUMP_SUPPRESS_FIRST & HEXDUMP_SUPPRESS_LAST flags. An inline wrapper function is provided for backwards compatibility with existing code, which maintains the original behaviour. Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 38 ++ lib/hexdump.c | 72 ++ 2 files changed, 89 insertions(+), 21 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index d7c77ed1a4cb..c014e5573665 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -479,13 +479,26 @@ enum { DUMP_PREFIX_ADDRESS, DUMP_PREFIX_OFFSET }; + +#define HEXDUMP_ASCII (1 << 0) +#define HEXDUMP_SUPPRESS_0X00 (1 << 1) +#define HEXDUMP_SUPPRESS_0XFF (1 << 2) +#define HEXDUMP_SUPPRESS_FIRST (1 << 3) +#define HEXDUMP_SUPPRESS_LAST (1 << 4) + +#define HEXDUMP_QUIET (HEXDUMP_SUPPRESS_0X00 | \ + HEXDUMP_SUPPRESS_0XFF | \ + HEXDUMP_SUPPRESS_FIRST | \ + HEXDUMP_SUPPRESS_LAST) + extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, bool ascii); + #ifdef CONFIG_PRINTK -extern 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); +extern void print_hex_dump_ext(const char *level, const char *prefix_str, + int prefix_type, int rowsize, int groupsize, + const void *buf, size_t len, u64 flags); #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)\ dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) @@ -494,18 +507,29 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len); #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ #else -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_ext(const char *level, const char *prefix_str, + int prefix_type, int rowsize, + int groupsize, const void *buf, + size_t len, u64 flags) { } static inline void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len) { } - #endif +static __always_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) +{ + print_hex_dump_ext(level, prefix_str, prefix_type, rowsize, groupsize, + buf, len, ascii ? HEXDUMP_ASCII : 0); +} + + #if defined(CONFIG_DYNAMIC_DEBUG) #define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ groupsize, buf, len, ascii)\ diff --git a/lib/hexdump.c b/lib/hexdump.c index b8a164814744..2f3bafb55a44 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -209,8 +209,21 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, EXPORT_SYMBOL(hex_dump_to_buffer); #ifdef CONFIG_PRINTK + +static bool buf_is_all(const u8 *buf, size_t len, u8 val) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (buf[i] != val) + return false; + } + + return true; +} + /** - * print_hex_dump - print a text hex dump to syslog for a binary blob of data + * print_hex_dump_ext: dump a binary blob of data to syslog in hexadecimal * @level: kernel log level (e.g. KERN_DEBUG) * @prefix_str: string to prefix each line with; * caller supplies trailing spaces for alignment if desired @@ -221,42 +234,73 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * @buf: data blob to dump * @len: number of bytes in the @buf * @ascii: include ASCII after the hex output + * @flags
Re: [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes
On Wed, 2019-04-10 at 13:17 +1000, Alastair D'Silva wrote: > From: Alastair D'Silva > > Some buffers may only be partially filled with useful data, while the > rest > is padded (typically with 0x00 or 0xff). > This patch introduces flags which allow lines of padding bytes to be > suppressed, making the output easier to interpret: > HEXDUMP_SUPPRESS_0X00, > HEXDUMP_SUPPRESS_0XFF > > The first and last lines are not suppressed by default, so the > function > always outputs something. This behaviour can be further controlled > with > the HEXDUMP_SUPPRESS_FIRST & HEXDUMP_SUPPRESS_LAST flags. > > An inline wrapper function is provided for backwards compatibility > with > existing code, which maintains the original behaviour. > > Signed-off-by: Alastair D'Silva > --- > > diff --git a/lib/hexdump.c b/lib/hexdump.c > index b8a164814744..2f3bafb55a44 100644 > --- a/lib/hexdump.c > +++ b/lib/hexdump.c > @@ -209,8 +209,21 @@ int hex_dump_to_buffer(const void *buf, size_t > len, int rowsize, int groupsize, > EXPORT_SYMBOL(hex_dump_to_buffer); > > #ifdef CONFIG_PRINTK > + > +static bool buf_is_all(const u8 *buf, size_t len, u8 val) > +{ > + size_t i; > + > + for (i = 0; i < len; i++) { > + if (buf[i] != val) > + return false; > + } > + > + return true; > +} > + > /** > - * print_hex_dump - print a text hex dump to syslog for a binary > blob of data > + * print_hex_dump_ext: dump a binary blob of data to syslog in > hexadecimal > * @level: kernel log level (e.g. KERN_DEBUG) > * @prefix_str: string to prefix each line with; > * caller supplies trailing spaces for alignment if desired > @@ -221,42 +234,73 @@ EXPORT_SYMBOL(hex_dump_to_buffer); > * @buf: data blob to dump > * @len: number of bytes in the @buf > * @ascii: include ASCII after the hex output This line should have been removed. I'll address it in V2. > + * @flags: A bitwise OR of the following flags: > + * HEXDUMP_ASCII: include ASCII after the hex output > + * HEXDUMP_SUPPRESS_0X00: suppress lines that are all 0x00 > + * (other than first or last) > + * HEXDUMP_SUPPRESS_0XFF: suppress lines that are all 0xff > + * (other than first or last) > + * HEXDUMP_SUPPRESS_FIRST: allows the first line to be > suppressed > + * HEXDUMP_SUPPRESS_LAST: allows the last line to be suppressed > + * If the first and last line may be > suppressed, > + * an empty buffer will not produce any > 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., > + * print_hex_dump_ext() works on one "line" of output at a time, > i.e., > * 16, 32 or 64 bytes of input data converted to hex + ASCII output. > - * print_hex_dump() iterates over the entire input @buf, breaking it > into > + * print_hex_dump_ext() 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); > + * print_hex_dump_ext(KERN_DEBUG, "raw data: ", > DUMP_PREFIX_ADDRESS, > + * 16, 1, frame->data, frame->len, HEXDUMP_ASCII); > * > * 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: > * 88089af0: 73727170 77767574 7b7a7978 > 7f7e7d7c pqrstuvwxyz{|}~. > */ -- Alastair D'Silva mob: 0423 762 819 skype: alastair_dsilva Twitter: @EvilDeece blog: http://alastair.d-silva.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/4] lib/hexdump.c: Allow 64 bytes per line
From: Alastair D'Silva With modern high resolution screens, we can display more data, which makes life a bit easier when debugging. Allow 64 bytes to be dumped per line. Signed-off-by: Alastair D'Silva --- lib/hexdump.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/hexdump.c b/lib/hexdump.c index 81b70ed37209..b8a164814744 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -80,14 +80,14 @@ EXPORT_SYMBOL(bin2hex); * 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 + * @rowsize: number of bytes to print per line; must be 16, 32 or 64 * @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. + * 16, 32 or 64 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. @@ -116,7 +116,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int ascii_column; int ret; - if (rowsize != 16 && rowsize != 32) + if (rowsize != 16 && rowsize != 32 && rowsize != 64) rowsize = 16; if (len > rowsize) /* limit to one line at a time */ @@ -216,7 +216,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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 + * @rowsize: number of bytes to print per line; must be 16, 32 or 64 * @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 @@ -227,7 +227,7 @@ EXPORT_SYMBOL(hex_dump_to_buffer); * 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. + * 16, 32 or 64 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. * @@ -246,9 +246,9 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, { const u8 *ptr = buf; int i, linelen, remaining = len; - unsigned char linebuf[32 * 3 + 2 + 32 + 1]; + unsigned char linebuf[64 * 3 + 2 + 64 + 1]; - if (rowsize != 16 && rowsize != 32) + if (rowsize != 16 && rowsize != 32 && rowsize != 64) rowsize = 16; for (i = 0; i < len; i += rowsize) { -- 2.20.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/4] lib/hexdump.c: Replace ascii bool in hex_dump_to_buffer with flags
From: Alastair D'Silva In order to support additional features in hex_dump_to_buffer, replace the ascii bool parameter with flags. Signed-off-by: Alastair D'Silva --- drivers/gpu/drm/i915/intel_engine_cs.c| 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 6 -- drivers/mailbox/mailbox-test.c| 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 3 ++- drivers/net/wireless/intel/iwlegacy/3945-mac.c| 2 +- drivers/platform/chrome/wilco_ec/debugfs.c| 3 ++- drivers/scsi/scsi_logging.c | 8 +++- drivers/staging/fbtft/fbtft-core.c| 2 +- fs/seq_file.c | 3 ++- include/linux/printk.h| 2 +- lib/hexdump.c | 15 --- lib/test_hexdump.c| 5 +++-- 14 files changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 49fa43ff02ba..fb133e729f9a 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1318,7 +1318,7 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len) WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, rowsize, sizeof(u32), line, sizeof(line), - false) >= sizeof(line)); + 0) >= sizeof(line)); drm_printf(m, "[%04zx] %s\n", pos, line); prev = buf + pos; diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index 386731ec2489..f13f34db6c17 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -84,7 +84,8 @@ send_mbox(struct isar_hw *isar, u8 his, u8 creg, u8 len, u8 *msg) while (l < (int)len) { hex_dump_to_buffer(msg + l, len - l, 32, 1, - isar->log, 256, 1); + isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; @@ -113,7 +114,8 @@ rcv_mbox(struct isar_hw *isar, u8 *msg) while (l < (int)isar->clsb) { hex_dump_to_buffer(msg + l, isar->clsb - l, 32, - 1, isar->log, 256, 1); + 1, isar->log, 256, + HEXDUMP_ASCII); pr_debug("%s: %s %02x: %s\n", isar->name, __func__, l, isar->log); l += 32; diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c index 4e4ac4be6423..2f9a094d0259 100644 --- a/drivers/mailbox/mailbox-test.c +++ b/drivers/mailbox/mailbox-test.c @@ -213,7 +213,7 @@ static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf, hex_dump_to_buffer(ptr, MBOX_BYTES_PER_LINE, MBOX_BYTES_PER_LINE, 1, touser + l, - MBOX_HEXDUMP_LINE_LEN, true); + MBOX_HEXDUMP_LINE_LEN, HEXDUMP_ASCII); ptr += MBOX_BYTES_PER_LINE; l += MBOX_HEXDUMP_LINE_LEN; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 0cc911f928b1..e954a31cee0c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -2992,7 +2992,7 @@ void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) unsigned int len = min(skb->len - i, 32U); hex_dump_to_buffer(>data[i], len, 32, 1, - buffer, sizeof(buffer), false); + buffer, sizeof(buffer), 0); netdev_dbg(netdev, " %#06x: %s\n", i, buffer); } diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c index eb1c6b03c329..b80adfa1f890 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c @@ -349,7 +349,7 @@ void xlgmac_print
[PATCH 4/4] lib/hexdump.c: Allow multiple groups to be separated by lines '|'
From: Alastair D'Silva With the wider display format, it can become hard to identify how many bytes into the line you are looking at. The patch adds new flags to hex_dump_to_buffer() and print_hex_dump() to print vertical lines to separate every N groups of bytes. eg. buf:: 454d414e 43415053|4e495f45 00584544 NAMESPAC|E_INDEX. buf:0010: 0002| | Signed-off-by: Alastair D'Silva --- include/linux/printk.h | 3 +++ lib/hexdump.c | 50 +- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index 82975853c400..d9e407e59059 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -485,6 +485,9 @@ enum { #define HEXDUMP_SUPPRESS_0XFF (1 << 2) #define HEXDUMP_SUPPRESS_FIRST (1 << 3) #define HEXDUMP_SUPPRESS_LAST (1 << 4) +#define HEXDUMP_2_GRP_LINES(1 << 5) +#define HEXDUMP_4_GRP_LINES(1 << 6) +#define HEXDUMP_8_GRP_LINES(1 << 7) #define HEXDUMP_QUIET (HEXDUMP_SUPPRESS_0X00 | \ HEXDUMP_SUPPRESS_0XFF | \ diff --git a/lib/hexdump.c b/lib/hexdump.c index 79db784577e7..d42f34b93b2c 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -76,6 +76,20 @@ char *bin2hex(char *dst, const void *src, size_t count) } EXPORT_SYMBOL(bin2hex); +static const char *group_separator(int group, u64 flags) +{ + if ((flags & HEXDUMP_8_GRP_LINES) && ((group - 1) % 8)) + return "|"; + + if ((flags & HEXDUMP_4_GRP_LINES) && ((group - 1) % 4)) + return "|"; + + if ((flags & HEXDUMP_2_GRP_LINES) && ((group - 1) % 2)) + return "|"; + + return " "; +} + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -86,6 +100,9 @@ EXPORT_SYMBOL(bin2hex); * @linebuflen: total size of @linebuf, including space for terminating NUL * @flags: A bitwise OR of the following flags: * HEXDUMP_ASCII: include ASCII after the hex output + * HEXDUMP_2_GRP_LINES:insert a '|' after every 2 groups + * HEXDUMP_4_GRP_LINES:insert a '|' after every 4 groups + * HEXDUMP_8_GRP_LINES:insert a '|' after every 8 groups * * hex_dump_to_buffer() works on one "line" of output at a time, i.e., * 16, 32 or 64 bytes of input data converted to hex + ASCII output. @@ -116,6 +133,7 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, int j, lx = 0; int ascii_column; int ret; + int line_chars = 0; if (rowsize != 16 && rowsize != 32 && rowsize != 64) rowsize = 16; @@ -141,7 +159,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%16.16llx", j ? " " : "", + "%s%16.16llx", + j ? group_separator(j, flags) : "", get_unaligned(ptr8 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -152,7 +171,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%8.8x", j ? " " : "", + "%s%8.8x", + j ? group_separator(j, flags) : "", get_unaligned(ptr4 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -163,7 +183,8 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, for (j = 0; j < ngroups; j++) { ret = snprintf(linebuf + lx, linebuflen - lx, - "%s%4.4x", j ? " " : "", + "%s%4.4x", + j ? group_separator(j, flags) : "", get_unaligned(ptr2 + j)); if (ret >= linebuflen - lx) goto overflow1; @@ -193,11 +214,26 @@ int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, goto overflow2; linebuf[lx++] = ' '; } + + if (flag