aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2012-07-30 17:40:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 20:25:14 -0400
commit31550a16a5d2af859e8a11839e8c6c6c9c92dfa7 (patch)
treeb38c5921bfeecdfc24e3146b15e21360a490e19e /lib
parent3715c5309f6d175c3053672b73fd4f73be16fd07 (diff)
vsprintf: add support of '%*ph[CDN]'
There are many places in the kernel where the drivers print small buffers as a hex string. This patch adds a support of the variable width buffer to print it as a hex string with a delimiter. The idea came from Pavel Roskin here: http://www.digipedia.pl/usenet/thread/18835/17449/ Sample output of pr_info("buf[%d:%d] %*phC\n", from, len, len, &buf[from]); could be look like this: [ 0.726130] buf[51:8] e8:16:b6:ef:e3:74:45:6e [ 0.750736] buf[59:15] 31:81:b8:3f:35:49:06:ae:df:32:06:05:4a:af:55 [ 0.757602] buf[17:5] ac:16:d5:2c:ef Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/vsprintf.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 225aa683e175..0e337541f005 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -655,6 +655,50 @@ char *resource_string(char *buf, char *end, struct resource *res,
655} 655}
656 656
657static noinline_for_stack 657static noinline_for_stack
658char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
659 const char *fmt)
660{
661 int i, len = 1; /* if we pass '%ph[CDN]', field witdh remains
662 negative value, fallback to the default */
663 char separator;
664
665 if (spec.field_width == 0)
666 /* nothing to print */
667 return buf;
668
669 if (ZERO_OR_NULL_PTR(addr))
670 /* NULL pointer */
671 return string(buf, end, NULL, spec);
672
673 switch (fmt[1]) {
674 case 'C':
675 separator = ':';
676 break;
677 case 'D':
678 separator = '-';
679 break;
680 case 'N':
681 separator = 0;
682 break;
683 default:
684 separator = ' ';
685 break;
686 }
687
688 if (spec.field_width > 0)
689 len = min_t(int, spec.field_width, 64);
690
691 for (i = 0; i < len && buf < end - 1; i++) {
692 buf = hex_byte_pack(buf, addr[i]);
693
694 if (buf < end && separator && i != len - 1)
695 *buf++ = separator;
696 }
697
698 return buf;
699}
700
701static noinline_for_stack
658char *mac_address_string(char *buf, char *end, u8 *addr, 702char *mac_address_string(char *buf, char *end, u8 *addr,
659 struct printf_spec spec, const char *fmt) 703 struct printf_spec spec, const char *fmt)
660{ 704{
@@ -974,6 +1018,13 @@ int kptr_restrict __read_mostly;
974 * correctness of the format string and va_list arguments. 1018 * correctness of the format string and va_list arguments.
975 * - 'K' For a kernel pointer that should be hidden from unprivileged users 1019 * - 'K' For a kernel pointer that should be hidden from unprivileged users
976 * - 'NF' For a netdev_features_t 1020 * - 'NF' For a netdev_features_t
1021 * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
1022 * a certain separator (' ' by default):
1023 * C colon
1024 * D dash
1025 * N no separator
1026 * The maximum supported length is 64 bytes of the input. Consider
1027 * to use print_hex_dump() for the larger input.
977 * 1028 *
978 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 1029 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
979 * function pointers are really function descriptors, which contain a 1030 * function pointers are really function descriptors, which contain a
@@ -1007,6 +1058,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1007 case 'R': 1058 case 'R':
1008 case 'r': 1059 case 'r':
1009 return resource_string(buf, end, ptr, spec, fmt); 1060 return resource_string(buf, end, ptr, spec, fmt);
1061 case 'h':
1062 return hex_string(buf, end, ptr, spec, fmt);
1010 case 'M': /* Colon separated: 00:01:02:03:04:05 */ 1063 case 'M': /* Colon separated: 00:01:02:03:04:05 */
1011 case 'm': /* Contiguous: 000102030405 */ 1064 case 'm': /* Contiguous: 000102030405 */
1012 /* [mM]F (FDDI) */ 1065 /* [mM]F (FDDI) */
@@ -1296,6 +1349,8 @@ qualifier:
1296 * %pI6c print an IPv6 address as specified by RFC 5952 1349 * %pI6c print an IPv6 address as specified by RFC 5952
1297 * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper 1350 * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
1298 * case. 1351 * case.
1352 * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
1353 * bytes of the input)
1299 * %n is ignored 1354 * %n is ignored
1300 * 1355 *
1301 * ** Please update Documentation/printk-formats.txt when making changes ** 1356 * ** Please update Documentation/printk-formats.txt when making changes **