aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c234
1 files changed, 167 insertions, 67 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 756ccafa9cec..b91839e9e892 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -25,6 +25,7 @@
25#include <linux/kallsyms.h> 25#include <linux/kallsyms.h>
26#include <linux/uaccess.h> 26#include <linux/uaccess.h>
27#include <linux/ioport.h> 27#include <linux/ioport.h>
28#include <net/addrconf.h>
28 29
29#include <asm/page.h> /* for PAGE_SIZE */ 30#include <asm/page.h> /* for PAGE_SIZE */
30#include <asm/div64.h> 31#include <asm/div64.h>
@@ -580,7 +581,7 @@ static char *symbol_string(char *buf, char *end, void *ptr,
580 unsigned long value = (unsigned long) ptr; 581 unsigned long value = (unsigned long) ptr;
581#ifdef CONFIG_KALLSYMS 582#ifdef CONFIG_KALLSYMS
582 char sym[KSYM_SYMBOL_LEN]; 583 char sym[KSYM_SYMBOL_LEN];
583 if (ext != 'f') 584 if (ext != 'f' && ext != 's')
584 sprint_symbol(sym, value); 585 sprint_symbol(sym, value);
585 else 586 else
586 kallsyms_lookup(value, NULL, NULL, NULL, sym); 587 kallsyms_lookup(value, NULL, NULL, NULL, sym);
@@ -630,60 +631,161 @@ static char *resource_string(char *buf, char *end, struct resource *res,
630} 631}
631 632
632static char *mac_address_string(char *buf, char *end, u8 *addr, 633static char *mac_address_string(char *buf, char *end, u8 *addr,
633 struct printf_spec spec) 634 struct printf_spec spec, const char *fmt)
634{ 635{
635 char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */ 636 char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
636 char *p = mac_addr; 637 char *p = mac_addr;
637 int i; 638 int i;
638 639
639 for (i = 0; i < 6; i++) { 640 for (i = 0; i < 6; i++) {
640 p = pack_hex_byte(p, addr[i]); 641 p = pack_hex_byte(p, addr[i]);
641 if (!(spec.flags & SPECIAL) && i != 5) 642 if (fmt[0] == 'M' && i != 5)
642 *p++ = ':'; 643 *p++ = ':';
643 } 644 }
644 *p = '\0'; 645 *p = '\0';
645 spec.flags &= ~SPECIAL;
646 646
647 return string(buf, end, mac_addr, spec); 647 return string(buf, end, mac_addr, spec);
648} 648}
649 649
650static char *ip6_addr_string(char *buf, char *end, u8 *addr, 650static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
651 struct printf_spec spec)
652{ 651{
653 char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
654 char *p = ip6_addr;
655 int i; 652 int i;
656 653
654 for (i = 0; i < 4; i++) {
655 char temp[3]; /* hold each IP quad in reverse order */
656 int digits = put_dec_trunc(temp, addr[i]) - temp;
657 if (leading_zeros) {
658 if (digits < 3)
659 *p++ = '0';
660 if (digits < 2)
661 *p++ = '0';
662 }
663 /* reverse the digits in the quad */
664 while (digits--)
665 *p++ = temp[digits];
666 if (i < 3)
667 *p++ = '.';
668 }
669
670 *p = '\0';
671 return p;
672}
673
674static char *ip6_compressed_string(char *p, const char *addr)
675{
676 int i;
677 int j;
678 int range;
679 unsigned char zerolength[8];
680 int longest = 1;
681 int colonpos = -1;
682 u16 word;
683 u8 hi;
684 u8 lo;
685 bool needcolon = false;
686 bool useIPv4;
687 struct in6_addr in6;
688
689 memcpy(&in6, addr, sizeof(struct in6_addr));
690
691 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
692
693 memset(zerolength, 0, sizeof(zerolength));
694
695 if (useIPv4)
696 range = 6;
697 else
698 range = 8;
699
700 /* find position of longest 0 run */
701 for (i = 0; i < range; i++) {
702 for (j = i; j < range; j++) {
703 if (in6.s6_addr16[j] != 0)
704 break;
705 zerolength[i]++;
706 }
707 }
708 for (i = 0; i < range; i++) {
709 if (zerolength[i] > longest) {
710 longest = zerolength[i];
711 colonpos = i;
712 }
713 }
714
715 /* emit address */
716 for (i = 0; i < range; i++) {
717 if (i == colonpos) {
718 if (needcolon || i == 0)
719 *p++ = ':';
720 *p++ = ':';
721 needcolon = false;
722 i += longest - 1;
723 continue;
724 }
725 if (needcolon) {
726 *p++ = ':';
727 needcolon = false;
728 }
729 /* hex u16 without leading 0s */
730 word = ntohs(in6.s6_addr16[i]);
731 hi = word >> 8;
732 lo = word & 0xff;
733 if (hi) {
734 if (hi > 0x0f)
735 p = pack_hex_byte(p, hi);
736 else
737 *p++ = hex_asc_lo(hi);
738 }
739 if (hi || lo > 0x0f)
740 p = pack_hex_byte(p, lo);
741 else
742 *p++ = hex_asc_lo(lo);
743 needcolon = true;
744 }
745
746 if (useIPv4) {
747 if (needcolon)
748 *p++ = ':';
749 p = ip4_string(p, &in6.s6_addr[12], false);
750 }
751
752 *p = '\0';
753 return p;
754}
755
756static char *ip6_string(char *p, const char *addr, const char *fmt)
757{
758 int i;
657 for (i = 0; i < 8; i++) { 759 for (i = 0; i < 8; i++) {
658 p = pack_hex_byte(p, addr[2 * i]); 760 p = pack_hex_byte(p, *addr++);
659 p = pack_hex_byte(p, addr[2 * i + 1]); 761 p = pack_hex_byte(p, *addr++);
660 if (!(spec.flags & SPECIAL) && i != 7) 762 if (fmt[0] == 'I' && i != 7)
661 *p++ = ':'; 763 *p++ = ':';
662 } 764 }
765
663 *p = '\0'; 766 *p = '\0';
664 spec.flags &= ~SPECIAL; 767 return p;
768}
769
770static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
771 struct printf_spec spec, const char *fmt)
772{
773 char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
774
775 if (fmt[0] == 'I' && fmt[2] == 'c')
776 ip6_compressed_string(ip6_addr, addr);
777 else
778 ip6_string(ip6_addr, addr, fmt);
665 779
666 return string(buf, end, ip6_addr, spec); 780 return string(buf, end, ip6_addr, spec);
667} 781}
668 782
669static char *ip4_addr_string(char *buf, char *end, u8 *addr, 783static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
670 struct printf_spec spec) 784 struct printf_spec spec, const char *fmt)
671{ 785{
672 char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */ 786 char ip4_addr[sizeof("255.255.255.255")];
673 char temp[3]; /* hold each IP quad in reverse order */
674 char *p = ip4_addr;
675 int i, digits;
676 787
677 for (i = 0; i < 4; i++) { 788 ip4_string(ip4_addr, addr, fmt[0] == 'i');
678 digits = put_dec_trunc(temp, addr[i]) - temp;
679 /* reverse the digits in the quad */
680 while (digits--)
681 *p++ = temp[digits];
682 if (i != 3)
683 *p++ = '.';
684 }
685 *p = '\0';
686 spec.flags &= ~SPECIAL;
687 789
688 return string(buf, end, ip4_addr, spec); 790 return string(buf, end, ip4_addr, spec);
689} 791}
@@ -697,16 +799,21 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr,
697 * 799 *
698 * - 'F' For symbolic function descriptor pointers with offset 800 * - 'F' For symbolic function descriptor pointers with offset
699 * - 'f' For simple symbolic function names without offset 801 * - 'f' For simple symbolic function names without offset
700 * - 'S' For symbolic direct pointers 802 * - 'S' For symbolic direct pointers with offset
803 * - 's' For symbolic direct pointers without offset
701 * - 'R' For a struct resource pointer, it prints the range of 804 * - 'R' For a struct resource pointer, it prints the range of
702 * addresses (not the name nor the flags) 805 * addresses (not the name nor the flags)
703 * - 'M' For a 6-byte MAC address, it prints the address in the 806 * - 'M' For a 6-byte MAC address, it prints the address in the
704 * usual colon-separated hex notation 807 * usual colon-separated hex notation
705 * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated 808 * - 'm' For a 6-byte MAC address, it prints the hex address without colons
706 * decimal for v4 and colon separated network-order 16 bit hex for v6) 809 * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
707 * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is 810 * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
708 * currently the same 811 * IPv6 uses colon separated network-order 16 bit hex with leading 0's
709 * 812 * - 'i' [46] for 'raw' IPv4/IPv6 addresses
813 * IPv6 omits the colons (01020304...0f)
814 * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
815 * - 'I6c' for IPv6 addresses printed as specified by
816 * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
710 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 817 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
711 * function pointers are really function descriptors, which contain a 818 * function pointers are really function descriptors, which contain a
712 * pointer to the real address. 819 * pointer to the real address.
@@ -721,25 +828,30 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
721 case 'F': 828 case 'F':
722 case 'f': 829 case 'f':
723 ptr = dereference_function_descriptor(ptr); 830 ptr = dereference_function_descriptor(ptr);
831 case 's':
724 /* Fallthrough */ 832 /* Fallthrough */
725 case 'S': 833 case 'S':
726 return symbol_string(buf, end, ptr, spec, *fmt); 834 return symbol_string(buf, end, ptr, spec, *fmt);
727 case 'R': 835 case 'R':
728 return resource_string(buf, end, ptr, spec); 836 return resource_string(buf, end, ptr, spec);
729 case 'm': 837 case 'M': /* Colon separated: 00:01:02:03:04:05 */
730 spec.flags |= SPECIAL; 838 case 'm': /* Contiguous: 000102030405 */
731 /* Fallthrough */ 839 return mac_address_string(buf, end, ptr, spec, fmt);
732 case 'M': 840 case 'I': /* Formatted IP supported
733 return mac_address_string(buf, end, ptr, spec); 841 * 4: 1.2.3.4
734 case 'i': 842 * 6: 0001:0203:...:0708
735 spec.flags |= SPECIAL; 843 * 6c: 1::708 or 1::1.2.3.4
736 /* Fallthrough */ 844 */
737 case 'I': 845 case 'i': /* Contiguous:
738 if (fmt[1] == '6') 846 * 4: 001.002.003.004
739 return ip6_addr_string(buf, end, ptr, spec); 847 * 6: 000102...0f
740 if (fmt[1] == '4') 848 */
741 return ip4_addr_string(buf, end, ptr, spec); 849 switch (fmt[1]) {
742 spec.flags &= ~SPECIAL; 850 case '6':
851 return ip6_addr_string(buf, end, ptr, spec, fmt);
852 case '4':
853 return ip4_addr_string(buf, end, ptr, spec, fmt);
854 }
743 break; 855 break;
744 } 856 }
745 spec.flags |= SMALL; 857 spec.flags |= SMALL;
@@ -958,10 +1070,12 @@ qualifier:
958 * @args: Arguments for the format string 1070 * @args: Arguments for the format string
959 * 1071 *
960 * This function follows C99 vsnprintf, but has some extensions: 1072 * This function follows C99 vsnprintf, but has some extensions:
961 * %pS output the name of a text symbol 1073 * %pS output the name of a text symbol with offset
1074 * %ps output the name of a text symbol without offset
962 * %pF output the name of a function pointer with its offset 1075 * %pF output the name of a function pointer with its offset
963 * %pf output the name of a function pointer without its offset 1076 * %pf output the name of a function pointer without its offset
964 * %pR output the address range in a struct resource 1077 * %pR output the address range in a struct resource
1078 * %n is ignored
965 * 1079 *
966 * The return value is the number of characters which would 1080 * The return value is the number of characters which would
967 * be generated for the given input, excluding the trailing 1081 * be generated for the given input, excluding the trailing
@@ -983,13 +1097,8 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
983 1097
984 /* Reject out-of-range values early. Large positive sizes are 1098 /* Reject out-of-range values early. Large positive sizes are
985 used for unknown buffer sizes. */ 1099 used for unknown buffer sizes. */
986 if (unlikely((int) size < 0)) { 1100 if (WARN_ON_ONCE((int) size < 0))
987 /* There can be only one.. */
988 static char warn = 1;
989 WARN_ON(warn);
990 warn = 0;
991 return 0; 1101 return 0;
992 }
993 1102
994 str = buf; 1103 str = buf;
995 end = buf + size; 1104 end = buf + size;
@@ -1417,11 +1526,7 @@ EXPORT_SYMBOL_GPL(vbin_printf);
1417 * a binary buffer that generated by vbin_printf. 1526 * a binary buffer that generated by vbin_printf.
1418 * 1527 *
1419 * The format follows C99 vsnprintf, but has some extensions: 1528 * The format follows C99 vsnprintf, but has some extensions:
1420 * %pS output the name of a text symbol 1529 * see vsnprintf comment for details.
1421 * %pF output the name of a function pointer with its offset
1422 * %pf output the name of a function pointer without its offset
1423 * %pR output the address range in a struct resource
1424 * %n is ignored
1425 * 1530 *
1426 * The return value is the number of characters which would 1531 * The return value is the number of characters which would
1427 * be generated for the given input, excluding the trailing 1532 * be generated for the given input, excluding the trailing
@@ -1439,13 +1544,8 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
1439 1544
1440 struct printf_spec spec = {0}; 1545 struct printf_spec spec = {0};
1441 1546
1442 if (unlikely((int) size < 0)) { 1547 if (WARN_ON_ONCE((int) size < 0))
1443 /* There can be only one.. */
1444 static char warn = 1;
1445 WARN_ON(warn);
1446 warn = 0;
1447 return 0; 1548 return 0;
1448 }
1449 1549
1450 str = buf; 1550 str = buf;
1451 end = buf + size; 1551 end = buf + size;