aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bitmap.c61
-rw-r--r--lib/vsprintf.c94
2 files changed, 96 insertions, 59 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index a13c7f4e325a..e85040ba1f22 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -383,28 +383,7 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
383int bitmap_scnprintf(char *buf, unsigned int buflen, 383int bitmap_scnprintf(char *buf, unsigned int buflen,
384 const unsigned long *maskp, int nmaskbits) 384 const unsigned long *maskp, int nmaskbits)
385{ 385{
386 int i, word, bit, len = 0; 386 return scnprintf(buf, buflen, "%*pb", nmaskbits, maskp);
387 unsigned long val;
388 const char *sep = "";
389 int chunksz;
390 u32 chunkmask;
391
392 chunksz = nmaskbits & (CHUNKSZ - 1);
393 if (chunksz == 0)
394 chunksz = CHUNKSZ;
395
396 i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
397 for (; i >= 0; i -= CHUNKSZ) {
398 chunkmask = ((1ULL << chunksz) - 1);
399 word = i / BITS_PER_LONG;
400 bit = i % BITS_PER_LONG;
401 val = (maskp[word] >> bit) & chunkmask;
402 len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
403 (chunksz+3)/4, val);
404 chunksz = CHUNKSZ;
405 sep = ",";
406 }
407 return len;
408} 387}
409EXPORT_SYMBOL(bitmap_scnprintf); 388EXPORT_SYMBOL(bitmap_scnprintf);
410 389
@@ -521,25 +500,6 @@ int bitmap_parse_user(const char __user *ubuf,
521} 500}
522EXPORT_SYMBOL(bitmap_parse_user); 501EXPORT_SYMBOL(bitmap_parse_user);
523 502
524/*
525 * bscnl_emit(buf, buflen, rbot, rtop, bp)
526 *
527 * Helper routine for bitmap_scnlistprintf(). Write decimal number
528 * or range to buf, suppressing output past buf+buflen, with optional
529 * comma-prefix. Return len of what was written to *buf, excluding the
530 * trailing \0.
531 */
532static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
533{
534 if (len > 0)
535 len += scnprintf(buf + len, buflen - len, ",");
536 if (rbot == rtop)
537 len += scnprintf(buf + len, buflen - len, "%d", rbot);
538 else
539 len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
540 return len;
541}
542
543/** 503/**
544 * bitmap_scnlistprintf - convert bitmap to list format ASCII string 504 * bitmap_scnlistprintf - convert bitmap to list format ASCII string
545 * @buf: byte buffer into which string is placed 505 * @buf: byte buffer into which string is placed
@@ -559,24 +519,7 @@ static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
559int bitmap_scnlistprintf(char *buf, unsigned int buflen, 519int bitmap_scnlistprintf(char *buf, unsigned int buflen,
560 const unsigned long *maskp, int nmaskbits) 520 const unsigned long *maskp, int nmaskbits)
561{ 521{
562 int len = 0; 522 return scnprintf(buf, buflen, "%*pbl", nmaskbits, maskp);
563 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
564 int cur, rbot, rtop;
565
566 if (buflen == 0)
567 return 0;
568 buf[0] = 0;
569
570 rbot = cur = find_first_bit(maskp, nmaskbits);
571 while (cur < nmaskbits) {
572 rtop = cur;
573 cur = find_next_bit(maskp, nmaskbits, cur+1);
574 if (cur >= nmaskbits || cur > rtop + 1) {
575 len = bscnl_emit(buf, buflen, rbot, rtop, len);
576 rbot = cur;
577 }
578 }
579 return len;
580} 523}
581EXPORT_SYMBOL(bitmap_scnlistprintf); 524EXPORT_SYMBOL(bitmap_scnlistprintf);
582 525
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 602d2081e713..b235c96167d3 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -794,6 +794,87 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
794} 794}
795 795
796static noinline_for_stack 796static noinline_for_stack
797char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
798 struct printf_spec spec, const char *fmt)
799{
800 const int CHUNKSZ = 32;
801 int nr_bits = max_t(int, spec.field_width, 0);
802 int i, chunksz;
803 bool first = true;
804
805 /* reused to print numbers */
806 spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 };
807
808 chunksz = nr_bits & (CHUNKSZ - 1);
809 if (chunksz == 0)
810 chunksz = CHUNKSZ;
811
812 i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ;
813 for (; i >= 0; i -= CHUNKSZ) {
814 u32 chunkmask, val;
815 int word, bit;
816
817 chunkmask = ((1ULL << chunksz) - 1);
818 word = i / BITS_PER_LONG;
819 bit = i % BITS_PER_LONG;
820 val = (bitmap[word] >> bit) & chunkmask;
821
822 if (!first) {
823 if (buf < end)
824 *buf = ',';
825 buf++;
826 }
827 first = false;
828
829 spec.field_width = DIV_ROUND_UP(chunksz, 4);
830 buf = number(buf, end, val, spec);
831
832 chunksz = CHUNKSZ;
833 }
834 return buf;
835}
836
837static noinline_for_stack
838char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
839 struct printf_spec spec, const char *fmt)
840{
841 int nr_bits = max_t(int, spec.field_width, 0);
842 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
843 int cur, rbot, rtop;
844 bool first = true;
845
846 /* reused to print numbers */
847 spec = (struct printf_spec){ .base = 10 };
848
849 rbot = cur = find_first_bit(bitmap, nr_bits);
850 while (cur < nr_bits) {
851 rtop = cur;
852 cur = find_next_bit(bitmap, nr_bits, cur + 1);
853 if (cur < nr_bits && cur <= rtop + 1)
854 continue;
855
856 if (!first) {
857 if (buf < end)
858 *buf = ',';
859 buf++;
860 }
861 first = false;
862
863 buf = number(buf, end, rbot, spec);
864 if (rbot < rtop) {
865 if (buf < end)
866 *buf = '-';
867 buf++;
868
869 buf = number(buf, end, rtop, spec);
870 }
871
872 rbot = cur;
873 }
874 return buf;
875}
876
877static noinline_for_stack
797char *mac_address_string(char *buf, char *end, u8 *addr, 878char *mac_address_string(char *buf, char *end, u8 *addr,
798 struct printf_spec spec, const char *fmt) 879 struct printf_spec spec, const char *fmt)
799{ 880{
@@ -1258,6 +1339,10 @@ int kptr_restrict __read_mostly;
1258 * - 'B' For backtraced symbolic direct pointers with offset 1339 * - 'B' For backtraced symbolic direct pointers with offset
1259 * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] 1340 * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
1260 * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] 1341 * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
1342 * - 'b[l]' For a bitmap, the number of bits is determined by the field
1343 * width which must be explicitly specified either as part of the
1344 * format string '%32b[l]' or through '%*b[l]', [l] selects
1345 * range-list format instead of hex format
1261 * - 'M' For a 6-byte MAC address, it prints the address in the 1346 * - 'M' For a 6-byte MAC address, it prints the address in the
1262 * usual colon-separated hex notation 1347 * usual colon-separated hex notation
1263 * - 'm' For a 6-byte MAC address, it prints the hex address without colons 1348 * - 'm' For a 6-byte MAC address, it prints the hex address without colons
@@ -1354,6 +1439,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1354 return resource_string(buf, end, ptr, spec, fmt); 1439 return resource_string(buf, end, ptr, spec, fmt);
1355 case 'h': 1440 case 'h':
1356 return hex_string(buf, end, ptr, spec, fmt); 1441 return hex_string(buf, end, ptr, spec, fmt);
1442 case 'b':
1443 switch (fmt[1]) {
1444 case 'l':
1445 return bitmap_list_string(buf, end, ptr, spec, fmt);
1446 default:
1447 return bitmap_string(buf, end, ptr, spec, fmt);
1448 }
1357 case 'M': /* Colon separated: 00:01:02:03:04:05 */ 1449 case 'M': /* Colon separated: 00:01:02:03:04:05 */
1358 case 'm': /* Contiguous: 000102030405 */ 1450 case 'm': /* Contiguous: 000102030405 */
1359 /* [mM]F (FDDI) */ 1451 /* [mM]F (FDDI) */
@@ -1689,6 +1781,8 @@ qualifier:
1689 * %pB output the name of a backtrace symbol with its offset 1781 * %pB output the name of a backtrace symbol with its offset
1690 * %pR output the address range in a struct resource with decoded flags 1782 * %pR output the address range in a struct resource with decoded flags
1691 * %pr output the address range in a struct resource with raw flags 1783 * %pr output the address range in a struct resource with raw flags
1784 * %pb output the bitmap with field width as the number of bits
1785 * %pbl output the bitmap as range list with field width as the number of bits
1692 * %pM output a 6-byte MAC address with colons 1786 * %pM output a 6-byte MAC address with colons
1693 * %pMR output a 6-byte MAC address with colons in reversed order 1787 * %pMR output a 6-byte MAC address with colons in reversed order
1694 * %pMF output a 6-byte MAC address with dashes 1788 * %pMF output a 6-byte MAC address with dashes