1 /* 2 * lib/hexdump.c 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. See README and COPYING for 7 * more details. 8 */ 9 10 #include <linux/types.h> 11 #include <linux/ctype.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 15 /** 16 * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory 17 * @buf: data blob to dump 18 * @len: number of bytes in the @buf 19 * @linebuf: where to put the converted data 20 * @linebuflen: total size of @linebuf, including space for terminating NUL 21 * 22 * hex_dump_to_buffer() works on one "line" of output at a time, i.e., 23 * 16 bytes of input data converted to hex + ASCII output. 24 * 25 * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data 26 * to a hex + ASCII dump at the supplied memory location. 27 * The converted output is always NUL-terminated. 28 * 29 * E.g.: 30 * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf)); 31 * 32 * example output buffer: 33 * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO 34 */ 35 void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf, 36 size_t linebuflen) 37 { 38 const u8 *ptr = buf; 39 u8 ch; 40 int j, lx = 0; 41 42 for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) { 43 if (j && !(j % 4)) 44 linebuf[lx++] = ' '; 45 ch = ptr[j]; 46 linebuf[lx++] = hex_asc(ch >> 4); 47 linebuf[lx++] = hex_asc(ch & 0x0f); 48 } 49 if ((lx + 2) < linebuflen) { 50 linebuf[lx++] = ' '; 51 linebuf[lx++] = ' '; 52 } 53 for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++) 54 linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.'; 55 linebuf[lx++] = '\0'; 56 } 57 EXPORT_SYMBOL(hex_dump_to_buffer); 58 59 /** 60 * print_hex_dump - print a text hex dump to syslog for a binary blob of data 61 * @level: kernel log level (e.g. KERN_DEBUG) 62 * @prefix_type: controls whether prefix of an offset, address, or none 63 * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE) 64 * @buf: data blob to dump 65 * @len: number of bytes in the @buf 66 * 67 * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump 68 * to the kernel log at the specified kernel log level, with an optional 69 * leading prefix. 70 * 71 * E.g.: 72 * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len); 73 * 74 * Example output using %DUMP_PREFIX_OFFSET: 75 * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO 76 * Example output using %DUMP_PREFIX_ADDRESS: 77 * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~. 78 */ 79 void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len) 80 { 81 u8 *ptr = buf; 82 int i, linelen, remaining = len; 83 unsigned char linebuf[100]; 84 85 for (i = 0; i < len; i += 16) { 86 linelen = min(remaining, 16); 87 remaining -= 16; 88 hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf)); 89 90 switch (prefix_type) { 91 case DUMP_PREFIX_ADDRESS: 92 printk("%s%*p: %s\n", level, 93 (int)(2 * sizeof(void *)), ptr + i, linebuf); 94 break; 95 case DUMP_PREFIX_OFFSET: 96 printk("%s%.8x: %s\n", level, i, linebuf); 97 break; 98 default: 99 printk("%s%s\n", level, linebuf); 100 break; 101 } 102 } 103 } 104 EXPORT_SYMBOL(print_hex_dump); 105