From patchwork Wed Apr 10 03:17:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alastair D'Silva X-Patchwork-Id: 10893007 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 85BD11805 for ; Wed, 10 Apr 2019 03:18:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 774A228585 for ; Wed, 10 Apr 2019 03:18:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6A91B28699; Wed, 10 Apr 2019 03:18:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B6F962862C for ; Wed, 10 Apr 2019 03:18:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726894AbfDJDSs (ORCPT ); Tue, 9 Apr 2019 23:18:48 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:43188 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726917AbfDJDSD (ORCPT ); Tue, 9 Apr 2019 23:18:03 -0400 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x3A39LF5043088 for ; Tue, 9 Apr 2019 23:18:02 -0400 Received: from e06smtp07.uk.ibm.com (e06smtp07.uk.ibm.com [195.75.94.103]) by mx0a-001b2d01.pphosted.com with ESMTP id 2rs7s8hbmu-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 09 Apr 2019 23:18:01 -0400 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 10 Apr 2019 04:17:58 +0100 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Wed, 10 Apr 2019 04:17:50 +0100 Received: from d06av22.portsmouth.uk.ibm.com (d06av22.portsmouth.uk.ibm.com [9.149.105.58]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x3A3Hnwn50921662 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2019 03:17:49 GMT Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 956844C059; Wed, 10 Apr 2019 03:17:49 +0000 (GMT) Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EEA0C4C046; Wed, 10 Apr 2019 03:17:48 +0000 (GMT) Received: from ozlabs.au.ibm.com (unknown [9.192.253.14]) by d06av22.portsmouth.uk.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2019 03:17:48 +0000 (GMT) Received: from adsilva.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id C7CCCA0236; Wed, 10 Apr 2019 13:17:47 +1000 (AEST) From: "Alastair D'Silva" To: alastair@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-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, linux-scsi@vger.kernel.org, linux-fbdev@vger.kernel.org, devel@driverdev.osuosl.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 2/4] lib/hexdump.c: Optionally suppress lines of filler bytes Date: Wed, 10 Apr 2019 13:17:18 +1000 X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190410031720.11067-1-alastair@au1.ibm.com> References: <20190410031720.11067-1-alastair@au1.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 19041003-0028-0000-0000-0000035F20B7 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19041003-0029-0000-0000-0000241E40D4 Message-Id: <20190410031720.11067-3-alastair@au1.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-04-10_02:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1904100022 Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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: 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: * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~. */ -void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, - int rowsize, int groupsize, - const void *buf, size_t len, bool ascii) +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; + + first_line = false; + 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); #if !defined(CONFIG_DYNAMIC_DEBUG) /** @@ -290,8 +334,8 @@ EXPORT_SYMBOL(print_hex_dump); void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len) { - print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1, - buf, len, true); + print_hex_dump_ext(KERN_DEBUG, prefix_str, prefix_type, 16, 1, + buf, len, HEXDUMP_ASCII); } EXPORT_SYMBOL(print_hex_dump_bytes); #endif /* !defined(CONFIG_DYNAMIC_DEBUG) */