diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2012-07-30 17:40:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 20:25:14 -0400 |
commit | 31550a16a5d2af859e8a11839e8c6c6c9c92dfa7 (patch) | |
tree | b38c5921bfeecdfc24e3146b15e21360a490e19e /lib | |
parent | 3715c5309f6d175c3053672b73fd4f73be16fd07 (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.c | 55 |
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 | ||
657 | static noinline_for_stack | 657 | static noinline_for_stack |
658 | char *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 | |||
701 | static noinline_for_stack | ||
658 | char *mac_address_string(char *buf, char *end, u8 *addr, | 702 | char *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 ** |