All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps
@ 2024-01-10  9:10 lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation lukas.funke-oss
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot
  Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Bin Meng,
	Evgeny Bachinin, Ilias Apalodimas, Marek Vasut,
	Mattijs Korpershoek, Roland Gaudig, Siddharth Vadapalli,
	Łukasz Stelmach

From: Lukas Funke <lukas.funke@weidmueller.com>


This series enables the 'setexpr' command to print "cpu list"-like
bitmaps based on the printk format specifier [1].

One use-case is to pass cpu list [2] based kernel parameter like
'isolcpu', 'nohz_full', irq affinity or RCU related CPU parameter to
the kernel via a separate firmware variable without exposing the
'bootargs' variable to directly.

Example:

=> env set value 0xdeadbeef
=> setexpr a fmt isolcpus=%32pbl $value
=> echo $a
isolcpus=0-3,5-7,9-13,15-16,18-19,21,23,25-28,30-31

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html


Changes in v3:
- Use generic find_next_zero_bit() from arch/arm/include/asm/bitops.h
- Redirect sandbox ffz() implementation to generic __ffs() impl
- Remove '%bp' from documentation
- Give an example output in the documentation
- Remove bitmap_string() conversion function since the same function
  can be achieved using other format specifier
- Dereference pointer argument (i.e. *value) in the
  'setexpr name fmt <format> value' case. This is currently only
  supported in the 'setexptr <name> [*]<value>' and
  'setexptr <name> [*]<value> <op> [*]<value2>' case

Changes in v2:
- Add bitmap format specifier to documentation

Lukas Funke (11):
  sandbox: add generic find_next_zero_bit implementation
  linux: bitmap.h: add 'for_each_set_bitrange' iteration macro
  test: cmd: setexpr: Add tests for bitmap string format
  doc: printf() codes: Add bitmap format specifier
  cmd: printf: Correctly handle field width
  lib: Add hextobarray() function
  lib: vsprintf: enable '%pbl' format specifier
  setexpr: rename 'get_arg()' to 'setexpr_get_arg()'
  setexpr: Promote 'setexpr_get_arg()' to a public function
  setexptr: Extend setexpr_get_arg() to handle pointer to memory
  cmd: printf: forward '%p' format string specifier

 arch/sandbox/include/asm/bitops.h | 60 +++++++++++++++++++------------
 cmd/printf.c                      | 53 ++++++++++++++++++++++++++-
 cmd/setexpr.c                     | 48 +++++++++++++++----------
 doc/develop/printf.rst            |  4 +++
 include/command.h                 | 27 ++++++++++++++
 include/linux/bitmap.h            |  7 ++++
 include/vsprintf.h                |  7 ++++
 lib/strto.c                       | 35 ++++++++++++++++++
 lib/vsprintf.c                    | 42 ++++++++++++++++++++++
 test/cmd/setexpr.c                | 22 ++++++++++++
 10 files changed, 263 insertions(+), 42 deletions(-)

-- 
2.30.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 02/11] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro lukas.funke-oss
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke

From: Lukas Funke <lukas.funke@weidmueller.com>

Add generic 'find_next_zero_bit()' implementation in order to enable the
use of the 'for_each_set_bitrange' macro. The implementation is currently
missing for the sandbox-arch and using the function results in a linker
error. The implementation is copied from the 'arm' implementation.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use generic find_next_zero_bit() from arch/arm/include/asm/bitops.h
- Redirect sandbox ffz() implementation to generic __ffs() impl

 arch/sandbox/include/asm/bitops.h | 60 +++++++++++++++++++------------
 1 file changed, 38 insertions(+), 22 deletions(-)

diff --git a/arch/sandbox/include/asm/bitops.h b/arch/sandbox/include/asm/bitops.h
index f27d5e98c5..6950916962 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -104,9 +104,6 @@ static inline int __test_and_change_bit(int nr, void *addr)
 	return (old & mask) != 0;
 }
 
-extern int find_first_zero_bit(void *addr, unsigned size);
-extern int find_next_zero_bit(void *addr, int size, int offset);
-
 /*
  * This routine doesn't need to be atomic.
  */
@@ -119,27 +116,46 @@ static inline int test_bit(int nr, const void *addr)
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
  */
-static inline unsigned long ffz(unsigned long word)
-{
-	int k;
-
-	word = ~word;
-	k = 31;
-	if (word & 0x0000ffff) {
-		k -= 16; word <<= 16;
-	}
-	if (word & 0x00ff0000) {
-		k -= 8;  word <<= 8;
-	}
-	if (word & 0x0f000000) {
-		k -= 4;  word <<= 4;
+#define ffz(x)  __ffs(~(x))
+
+#define find_first_zero_bit(addr, size) \
+	find_next_zero_bit((addr), (size), 0)
+
+static inline int find_next_zero_bit(const unsigned long *addr, int size,
+				     int offset) {
+	unsigned long *p = ((unsigned long *)addr) + (offset / BITS_PER_LONG);
+	unsigned long result = offset & ~(BITS_PER_LONG - 1);
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= (BITS_PER_LONG - 1);
+	if (offset) {
+		tmp = *(p++);
+		tmp |= ~0UL >> (BITS_PER_LONG - offset);
+		if (size < BITS_PER_LONG)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= BITS_PER_LONG;
+		result += BITS_PER_LONG;
 	}
-	if (word & 0x30000000) {
-		k -= 2;  word <<= 2;
+	while (size & ~(BITS_PER_LONG - 1)) {
+		tmp = *(p++);
+		if (~tmp)
+			goto found_middle;
+		result += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
 	}
-	if (word & 0x40000000)
-		k -= 1;
-	return k;
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
 }
 
 /*
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 02/11] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 03/11] test: cmd: setexpr: Add tests for bitmap string format lukas.funke-oss
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke

From: Lukas Funke <lukas.funke@weidmueller.com>

Add 'for_each_set_bitrange' (from Linux kernel) in order to iterate
over each set bitrange of a bitmap. This becomes handy if one wants
to generate a cpu list i.e. for isolcpu or nohz_full.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 include/linux/bitmap.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f..9714533078 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -159,6 +159,13 @@ static inline unsigned long find_first_bit(const unsigned long *addr, unsigned l
 	     (bit) < (size);					\
 	     (bit) = find_next_bit((addr), (size), (bit) + 1))
 
+#define for_each_set_bitrange(b, e, addr, size)			\
+	for ((b) = 0;						\
+	     (b) = find_next_bit((addr), (size), b),		\
+	     (e) = find_next_zero_bit((addr), (size), (b) + 1),	\
+	     (b) < (size);					\
+	     (b) = (e) + 1)
+
 static inline unsigned long
 bitmap_find_next_zero_area(unsigned long *map,
 			   unsigned long size,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 03/11] test: cmd: setexpr: Add tests for bitmap string format
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 02/11] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 04/11] doc: printf() codes: Add bitmap format specifier lukas.funke-oss
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke

From: Lukas Funke <lukas.funke@weidmueller.com>

Add tests to test the bitmap format specifier. Test different bit
widths and access to memory by pointer.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

(no changes since v1)

 test/cmd/setexpr.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index 312593e1e3..c536c9e963 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -465,6 +465,28 @@ static int setexpr_test_fmt(struct unit_test_state *uts)
 	ut_asserteq(1, run_command("setexpr fred fmt hello% bf", 0));
 	/* Error exceeding maximum string length */
 	ut_asserteq(1, run_command("setexpr fred fmt \"%0128d\" 456", 0));
+	/* Test bitmask long string */
+	ut_assertok(run_command("setexpr fred fmt isolcpu=%64pbl 0x1F1", 0));
+	ut_asserteq_str("isolcpu=0,4-8", env_get("fred"));
+	/* Test bitmask long string (more complicated) */
+	ut_assertok(run_command("setexpr fred fmt nohz_full=%32pbl 0x55555555", 0));
+	ut_asserteq_str("nohz_full=0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30", env_get("fred"));
+	ut_assertok(run_command("setexpr fred fmt %64pbl 0xdeadbeef", 0));
+	ut_asserteq_str("0-3,5-7,9-13,15-16,18-19,21,23,25-28,30-31", env_get("fred"));
+	/* Test bitmask on 64...256 */
+	ut_assertok(run_command("setexpr fred fmt %64pbl 0xf0f0f0f0f0f0f0f0", 0));
+	ut_asserteq_str("4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63", env_get("fred"));
+	ut_assertok(run_command("setexpr fred fmt %128pbl 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0", 0));
+	ut_asserteq_str("4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63,68-71,76-79,84-87,92-95,100-103,108-111,116-119,124-127", env_get("fred"));
+	/* clear lower bitmask, otherwise output gets truncated */
+	ut_assertok(run_command("setexpr fred fmt %256pbl 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000", 0));
+	ut_asserteq_str("132-135,140-143,148-151,156-159,164-167,172-175,180-183,188-191,196-199,204-207,212-215,220-223,228-231,236-239,244-247,252-255", env_get("fred"));
+	/* Test memory access */
+	memset(buf, 0, BUF_SIZE);
+	ut_assertok(run_command("env set myaddr 0x0;"
+							"mw.l $myaddr 0xdeadbeef 1;"
+							"setexpr fred fmt %64pbl *$myaddr", 0));
+	ut_asserteq_str("0-3,5-7,9-13,15-16,18-19,21,23,25-28,30-31", env_get("fred"));
 
 	unmap_sysmem(buf);
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 04/11] doc: printf() codes: Add bitmap format specifier
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (2 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 03/11] test: cmd: setexpr: Add tests for bitmap string format lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 05/11] cmd: printf: Correctly handle field width lukas.funke-oss
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Siddharth Vadapalli

From: Lukas Funke <lukas.funke@weidmueller.com>

Add '%pbl' printf format specifier as descriped in [1].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

Changes in v3:
- Remove '%bp' from documentation
- Give an example output in the documentation

 doc/develop/printf.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst
index 99d05061b1..8220c7c12b 100644
--- a/doc/develop/printf.rst
+++ b/doc/develop/printf.rst
@@ -165,6 +165,10 @@ Pointers
 	* phys_size_t
 	* resource_size_t
 
+%pbl
+        '%pbl' outputs a bitmap as range list with field width as
+        the number of bits. e.g. '0,8-11,13-16,18-19,22-25,27,29,31'
+
 %pD
         prints a UEFI device path
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 05/11] cmd: printf: Correctly handle field width
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (3 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 04/11] doc: printf() codes: Add bitmap format specifier lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 06/11] lib: Add hextobarray() function lukas.funke-oss
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Roland Gaudig

From: Lukas Funke <lukas.funke@weidmueller.com>

Correctly parse the field width from the format specifier. Before this
commit the field_width was simply ignored.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

(no changes since v1)

 cmd/printf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/printf.c b/cmd/printf.c
index 0c6887e0d6..f56543b79e 100644
--- a/cmd/printf.c
+++ b/cmd/printf.c
@@ -517,7 +517,7 @@ static char **print_formatted(struct print_inf *inf, char *f, char **argv, int *
 					field_width = get_width_prec(*argv++);
 			} else {
 				while (isdigit(*f)) {
-					++f;
+					field_width = field_width * 10 + *(f++) - '0';
 					++direc_length;
 				}
 			}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 06/11] lib: Add hextobarray() function
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (4 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 05/11] cmd: printf: Correctly handle field width lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier lukas.funke-oss
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke

From: Lukas Funke <lukas.funke@weidmueller.com>

Add a 'hextobarray()' function which converts a hex string to it's
memory representation. This can be used to represent large integer
numbers or bitmasks which do not fit in a regular unsigned long value.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

(no changes since v1)

 include/vsprintf.h |  7 +++++++
 lib/strto.c        | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index ed8a060ee1..82c8bf029e 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -368,4 +368,11 @@ int vsscanf(const char *inp, char const *fmt0, va_list ap);
  */
 int sscanf(const char *buf, const char *fmt, ...);
 
+/**
+ * hextobarray - Convert a hex-string to a byte array
+ * @cp:		hex string to convert
+ * Return: a pointer to a byte array, -ENOMEM on error
+ */
+uchar *hextobarray(const char *cp);
+
 #endif
diff --git a/lib/strto.c b/lib/strto.c
index 5157332d6c..eb507e4ab8 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -13,6 +13,7 @@
 #include <malloc.h>
 #include <vsprintf.h>
 #include <linux/ctype.h>
+#include <linux/err.h>
 
 /* from lib/kstrtox.c */
 static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
@@ -73,6 +74,40 @@ ulong simple_strtoul(const char *cp, char **endp, uint base)
 	return result;
 }
 
+uchar *hextobarray(const char *cp)
+{
+	int i, len;
+	__maybe_unused unsigned int base;
+	__maybe_unused const char *endptr;
+	unsigned char *array;
+
+	len = strlen(cp);
+	array = (unsigned char *)malloc(len);
+	if (!array)
+		return ERR_PTR(-ENOMEM);
+
+	memset(array, 0, len);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	endptr = (cp + len - 1);
+	for (i = 0; i < len && endptr > cp; i++) {
+		array[i] |= decode_digit(*(endptr));
+		endptr--;
+		array[i] |= decode_digit(*endptr) << 4;
+		endptr--;
+	}
+#else
+	cp = _parse_integer_fixup_radix(cp, &base);
+	for (i = 0; i < len && *cp; i++) {
+		array[i] |= decode_digit(*cp) << 4;
+		cp++;
+		array[i] |= decode_digit(*cp);
+		cp++;
+	}
+#endif
+	return array;
+}
+
 ulong hextoul(const char *cp, char **endp)
 {
 	return simple_strtoul(cp, endp, 16);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (5 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 06/11] lib: Add hextobarray() function lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-18 20:22   ` Tom Rini
  2024-01-10  9:10 ` [PATCH v3 08/11] setexpr: rename 'get_arg()' to 'setexpr_get_arg()' lukas.funke-oss
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Bin Meng

From: Lukas Funke <lukas.funke@weidmueller.com>

The commit enables vsprintf() to handle the '%pbl' format specifier
in order to print bitmaps and its derivatives such as cpumask and
nodemask [1]. This can be used to derive kernel boot parameters from
bitmaks such as 'isolcpu' or 'nohz_full' [2].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

Changes in v3:
- Remove bitmap_string() conversion function since the same function
  can be achieved using other format specifier

 lib/vsprintf.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 27ea9c907a..e1779d75f8 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/bitmap.h>
 
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
@@ -389,6 +390,33 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
 		      flags & ~SPECIAL);
 }
 
+static char *bitmap_list_string(char *buf, char *end, unsigned long *addr,
+				int field_width, int precision, int flags)
+{
+	int nr_bits = max_t(int, field_width, 0);
+	int first = 1;
+	int rbot, rtop;
+
+	for_each_set_bitrange(rbot, rtop, addr, nr_bits) {
+		if (!first) {
+			if (buf < end)
+				*buf = ',';
+			buf++;
+		}
+		first = 0;
+
+		buf = number(buf, end, rbot, 10, 0, -1, 0);
+		if (rtop == rbot + 1)
+			continue;
+
+		if (buf < end)
+			*buf = '-';
+		buf = number(++buf, end, rtop - 1, 10, 0, -1, 0);
+	}
+
+	return buf;
+}
+
 #ifdef CONFIG_LIB_UUID
 /*
  * This works (roughly) the same way as Linux's.
@@ -502,6 +530,20 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 					       precision, flags);
 		flags &= ~SPECIAL;
 		break;
+	case 'b':
+		switch (fmt[1]) {
+		case 'l':
+			/* if the field width is not a multiple of the underlying
+			 * datatype (ulong), we get incorrect results from the bit twiddle
+			 * macros. Thus, round up to a multiple of field width of ulong
+			 */
+			field_width = field_width % BITS_PER_LONG ?
+				ALIGN(field_width, BITS_PER_LONG) : field_width;
+			return bitmap_list_string(buf, end, ptr, field_width,
+							precision, flags);
+		default:
+			return ERR_PTR(-EINVAL);
+		}
 #ifdef CONFIG_LIB_UUID
 	case 'U':
 		return uuid_string(buf, end, ptr, field_width, precision,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 08/11] setexpr: rename 'get_arg()' to 'setexpr_get_arg()'
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (6 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 09/11] setexpr: Promote 'setexpr_get_arg()' to a public function lukas.funke-oss
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot
  Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Łukasz Stelmach

From: Lukas Funke <lukas.funke@weidmueller.com>

Prefix the get_arg() function with 'setexpr_' in order to prepare
the removal of the static specifier. The prefix shall denote the origin
of the function.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

(no changes since v1)

 cmd/setexpr.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index 233471f6cb..bc57d41448 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -34,7 +34,7 @@ struct expr_arg {
 	};
 };
 
-static int get_arg(char *s, int w, struct expr_arg *argp)
+static int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 {
 	struct expr_arg arg;
 
@@ -388,7 +388,7 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
 
 	w = cmd_get_data_size(argv[0], 4);
 
-	if (get_arg(argv[2], w, &aval))
+	if (setexpr_get_arg(argv[2], w, &aval))
 		return CMD_RET_FAILURE;
 
 	/* format string assignment: "setexpr name fmt %d value" */
@@ -441,7 +441,7 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
 	if (strlen(argv[3]) != 1)
 		return CMD_RET_USAGE;
 
-	if (get_arg(argv[4], w, &bval)) {
+	if (setexpr_get_arg(argv[4], w, &bval)) {
 		if (w == CMD_DATA_SIZE_STR)
 			free(aval.sval);
 		return CMD_RET_FAILURE;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 09/11] setexpr: Promote 'setexpr_get_arg()' to a public function
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (7 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 08/11] setexpr: rename 'get_arg()' to 'setexpr_get_arg()' lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 10/11] setexptr: Extend setexpr_get_arg() to handle pointer to memory lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 11/11] cmd: printf: forward '%p' format string specifier lukas.funke-oss
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot
  Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Evgeny Bachinin,
	Ilias Apalodimas, Marek Vasut, Mattijs Korpershoek,
	Łukasz Stelmach

From: Lukas Funke <lukas.funke@weidmueller.com>

Promote 'setexpr_get_arg()' to a public function in order to use it
from the setexpr command and in the printf-internals.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

(no changes since v1)

 cmd/setexpr.c     | 15 +--------------
 include/command.h | 27 +++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index bc57d41448..9caa68d20d 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -21,20 +21,7 @@
 
 #define MAX_STR_LEN 128
 
-/**
- * struct expr_arg: Holds an argument to an expression
- *
- * @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
- * @sval: String value (if width is CMD_DATA_SIZE_STR)
- */
-struct expr_arg {
-	union {
-		ulong ival;
-		char *sval;
-	};
-};
-
-static int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
+int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 {
 	struct expr_arg arg;
 
diff --git a/include/command.h b/include/command.h
index 4cec634545..d0aa98b1f6 100644
--- a/include/command.h
+++ b/include/command.h
@@ -248,6 +248,33 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
 int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size,
 		      const char *r, const char *s, bool global);
 
+/**
+ * struct expr_arg: Holds an argument to an expression
+ *
+ * @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
+ * @sval: String value (if width is CMD_DATA_SIZE_STR)
+ * @bmap: Bitmap value (if width is > u64)
+ */
+struct expr_arg {
+	union {
+		ulong ival;
+		char *sval;
+		uchar *bmap;
+	};
+};
+
+/**
+ * setexpr_get_arg() - Converts a string argument to it's value. If argument
+ * starts with a '*' treat it as a pointer and dereference.
+ *
+ * @s: Argument string
+ * @w: Byte width of argument
+ * @argp: Pointer where the value should be stored
+ *
+ * Return: 0 on success, -EINVAL on failure
+ */
+int setexpr_get_arg(char *s, int w, struct expr_arg *argp);
+
 /*
  * Error codes that commands return to cmd_process(). We use the standard 0
  * and 1 for success and failure, but add one more case - failure with a
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 10/11] setexptr: Extend setexpr_get_arg() to handle pointer to memory
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (8 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 09/11] setexpr: Promote 'setexpr_get_arg()' to a public function lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  2024-01-10  9:10 ` [PATCH v3 11/11] cmd: printf: forward '%p' format string specifier lukas.funke-oss
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot
  Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Łukasz Stelmach

From: Lukas Funke <lukas.funke@weidmueller.com>

Extend setexpr_get_arg() function in order to handle bitmaps with
length greater than 8 byte. If the bitmap is provided as hex string
the string is parsed into a bitmap.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

(no changes since v1)

 cmd/setexpr.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index 9caa68d20d..fed457bb7e 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -17,6 +17,7 @@
 #include <malloc.h>
 #include <mapmem.h>
 #include <linux/sizes.h>
+#include <linux/err.h>
 #include "printf.h"
 
 #define MAX_STR_LEN 128
@@ -24,6 +25,8 @@
 int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 {
 	struct expr_arg arg;
+	uchar *bmap;
+	ulong val;
 
 	/*
 	 * If the parameter starts with a '*' then assume it is a pointer to
@@ -32,7 +35,6 @@ int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 	if (s[0] == '*') {
 		ulong *p;
 		ulong addr;
-		ulong val;
 		int len;
 		char *str;
 
@@ -71,17 +73,38 @@ int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 			unmap_sysmem(p);
 			arg.ival = val;
 			break;
-		default:
+#if BITS_PER_LONG == 64
+		case 8:
 			p = map_sysmem(addr, sizeof(ulong));
 			val = *p;
 			unmap_sysmem(p);
 			arg.ival = val;
 			break;
+#endif
+		default:
+			p = map_sysmem(addr, w);
+			bmap = malloc(w);
+			if (!bmap) {
+				printf("Out of memory\n");
+				return -ENOMEM;
+			}
+			memcpy(bmap, p, w);
+			arg.bmap = bmap;
+			unmap_sysmem(p);
 		}
 	} else {
 		if (w == CMD_DATA_SIZE_STR)
 			return -EINVAL;
-		arg.ival = hextoul(s, NULL);
+		if (w > sizeof(ulong)) {
+			bmap = hextobarray(s);
+			if (IS_ERR(bmap)) {
+				printf("Out of memory\n");
+				return -ENOMEM;
+			}
+			arg.bmap = bmap;
+		} else {
+			arg.ival = hextoul(s, NULL);
+		}
 	}
 	*argp = arg;
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 11/11] cmd: printf: forward '%p' format string specifier
  2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
                   ` (9 preceding siblings ...)
  2024-01-10  9:10 ` [PATCH v3 10/11] setexptr: Extend setexpr_get_arg() to handle pointer to memory lukas.funke-oss
@ 2024-01-10  9:10 ` lukas.funke-oss
  10 siblings, 0 replies; 15+ messages in thread
From: lukas.funke-oss @ 2024-01-10  9:10 UTC (permalink / raw)
  To: u-boot; +Cc: Simon Glass, Heinrich Schuchardt, Lukas Funke, Roland Gaudig

From: Lukas Funke <lukas.funke@weidmueller.com>

Forward '%p' format specifier to the underlying format logic in order
to print pointers, especially bitmaps.

Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
---

Changes in v3:
- Dereference pointer argument (i.e. *value) in the
  'setexpr name fmt <format> value' case. This is currently only
  supported in the 'setexptr <name> [*]<value>' and
  'setexptr <name> [*]<value> <op> [*]<value2>' case

 cmd/printf.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/cmd/printf.c b/cmd/printf.c
index f56543b79e..2e54faf339 100644
--- a/cmd/printf.c
+++ b/cmd/printf.c
@@ -85,11 +85,13 @@
  */
 
 #include <common.h>
+#include <command.h>
 #include <ctype.h>
 #include <errno.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <linux/bitmap.h>
 
 #define WANT_HEX_ESCAPES 0
 #define PRINT_CONVERSION_ERROR 1
@@ -476,6 +478,38 @@ static int get_width_prec(const char *str)
 	return (int)v;
 }
 
+static int print_pointer(struct print_inf *inf, char *format,
+			 unsigned int fmt_length, int field_width,
+			 int precision, const char *argument)
+{
+	struct expr_arg aval;
+
+	if (setexpr_get_arg(skip_whitespace(argument), field_width >> 3, &aval))
+		return CMD_RET_FAILURE;
+
+	if (field_width > BITS_PER_LONG) {
+		printf_str(inf, format, aval.bmap);
+		free(aval.bmap);
+	} else {
+		printf_str(inf, format, &aval.ival);
+	}
+
+	switch (inf->error) {
+	case 0:
+		return 0;
+	case PRINT_SIZE_ERROR:
+		printf("printf: size error\n"); break;
+	case PRINT_CONVERSION_ERROR:
+		printf("printf: conversion error\n"); break;
+	case PRINT_TRUNCATED_ERROR:
+		printf("printf: output truncated\n"); break;
+	default:
+		printf("printf: unknown error\n");
+	}
+
+	return -1;
+}
+
 /* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
  * Return advanced ARGV.
  */
@@ -536,6 +570,23 @@ static char **print_formatted(struct print_inf *inf, char *f, char **argv, int *
 					}
 				}
 			}
+			if (*f == 'p') {
+				static const char ptr_format_chars[] = "bl";
+				++f;
+				++direc_length;
+				char *p = strchr(ptr_format_chars, *f);
+				/* consume whole format token */
+				while (*f != '\0' && *(p++) == *f) {
+					++f;
+					++direc_length;
+				}
+				if (print_pointer(inf, direc_start, direc_length,
+						  field_width, precision, *argv++)) {
+					return saved_argv - 1;
+				}
+				f--;
+				break;
+			}
 
 			/* Remove "lLhz" size modifiers, repeatedly.
 			 * bash does not like "%lld", but coreutils
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier
  2024-01-10  9:10 ` [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier lukas.funke-oss
@ 2024-01-18 20:22   ` Tom Rini
  2024-01-23 14:48     ` Lukas Funke
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2024-01-18 20:22 UTC (permalink / raw)
  To: lukas.funke-oss
  Cc: u-boot, Simon Glass, Heinrich Schuchardt, Lukas Funke, Bin Meng

[-- Attachment #1: Type: text/plain, Size: 965 bytes --]

On Wed, Jan 10, 2024 at 10:10:33AM +0100, lukas.funke-oss@weidmueller.com wrote:

> From: Lukas Funke <lukas.funke@weidmueller.com>
> 
> The commit enables vsprintf() to handle the '%pbl' format specifier
> in order to print bitmaps and its derivatives such as cpumask and
> nodemask [1]. This can be used to derive kernel boot parameters from
> bitmaks such as 'isolcpu' or 'nohz_full' [2].
> 
> [1] https://www.kernel.org/doc/Documentation/printk-formats.txt
> [2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
> 
> Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>

This breaks building ARC platforms, and possibly others.  Note that
tools/buildman/buildman is happy to fetch toolchains for you, and in
this case it's also just the current kernel.org cross-toolchain. Please
see https://docs.u-boot.org/en/latest/develop/ci_testing.html about how
to trigger a CI run prior to sending v4, thanks.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier
  2024-01-18 20:22   ` Tom Rini
@ 2024-01-23 14:48     ` Lukas Funke
  2024-01-24  1:32       ` Tom Rini
  0 siblings, 1 reply; 15+ messages in thread
From: Lukas Funke @ 2024-01-23 14:48 UTC (permalink / raw)
  To: Tom Rini; +Cc: u-boot, Simon Glass, Heinrich Schuchardt, Lukas Funke, Bin Meng

Hi Tom,

On 18.01.2024 21:22, Tom Rini wrote:
> On Wed, Jan 10, 2024 at 10:10:33AM +0100, lukas.funke-oss@weidmueller.com wrote:
> 
>> From: Lukas Funke <lukas.funke@weidmueller.com>
>>
>> The commit enables vsprintf() to handle the '%pbl' format specifier
>> in order to print bitmaps and its derivatives such as cpumask and
>> nodemask [1]. This can be used to derive kernel boot parameters from
>> bitmaks such as 'isolcpu' or 'nohz_full' [2].
>>
>> [1] https://www.kernel.org/doc/Documentation/printk-formats.txt
>> [2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
>>
>> Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
> 
> This breaks building ARC platforms, and possibly others.  Note that
> tools/buildman/buildman is happy to fetch toolchains for you, and in
> this case it's also just the current kernel.org cross-toolchain. Please
> see https://docs.u-boot.org/en/latest/develop/ci_testing.html about how
> to trigger a CI run prior to sending v4, thanks.
> 

Thanks for the input. I ran the pipeline on github and it failed for 
riscv, m86k, x86_64. The reason is the missing 'find_next_zero_bit()' 
implementation (actually it's faulty on x86_64). What is a good way to 
cope with this problem? My suggestions would be:

- Add a generic 'find_next_zero_bit()'. This would be the
'Linux way' and requires refactoring of the bitops header.
- Add ifdef-macro/kconfig to only enable the format specifier only for 
the supported platforms. This would be the 'quick way'.

What would be your or the maintainers preferred solution?

Best regards
Lukas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier
  2024-01-23 14:48     ` Lukas Funke
@ 2024-01-24  1:32       ` Tom Rini
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Rini @ 2024-01-24  1:32 UTC (permalink / raw)
  To: Lukas Funke
  Cc: u-boot, Simon Glass, Heinrich Schuchardt, Lukas Funke, Bin Meng

[-- Attachment #1: Type: text/plain, Size: 1599 bytes --]

On Tue, Jan 23, 2024 at 03:48:10PM +0100, Lukas Funke wrote:
> Hi Tom,
> 
> On 18.01.2024 21:22, Tom Rini wrote:
> > On Wed, Jan 10, 2024 at 10:10:33AM +0100, lukas.funke-oss@weidmueller.com wrote:
> > 
> > > From: Lukas Funke <lukas.funke@weidmueller.com>
> > > 
> > > The commit enables vsprintf() to handle the '%pbl' format specifier
> > > in order to print bitmaps and its derivatives such as cpumask and
> > > nodemask [1]. This can be used to derive kernel boot parameters from
> > > bitmaks such as 'isolcpu' or 'nohz_full' [2].
> > > 
> > > [1] https://www.kernel.org/doc/Documentation/printk-formats.txt
> > > [2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
> > > 
> > > Signed-off-by: Lukas Funke <lukas.funke@weidmueller.com>
> > 
> > This breaks building ARC platforms, and possibly others.  Note that
> > tools/buildman/buildman is happy to fetch toolchains for you, and in
> > this case it's also just the current kernel.org cross-toolchain. Please
> > see https://docs.u-boot.org/en/latest/develop/ci_testing.html about how
> > to trigger a CI run prior to sending v4, thanks.
> > 
> 
> Thanks for the input. I ran the pipeline on github and it failed for riscv,
> m86k, x86_64. The reason is the missing 'find_next_zero_bit()'
> implementation (actually it's faulty on x86_64). What is a good way to cope
> with this problem? My suggestions would be:
> 
> - Add a generic 'find_next_zero_bit()'. This would be the
> 'Linux way' and requires refactoring of the bitops header.

Yes, this way please, thanks.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2024-01-24  1:32 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-10  9:10 [PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 02/11] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 03/11] test: cmd: setexpr: Add tests for bitmap string format lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 04/11] doc: printf() codes: Add bitmap format specifier lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 05/11] cmd: printf: Correctly handle field width lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 06/11] lib: Add hextobarray() function lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier lukas.funke-oss
2024-01-18 20:22   ` Tom Rini
2024-01-23 14:48     ` Lukas Funke
2024-01-24  1:32       ` Tom Rini
2024-01-10  9:10 ` [PATCH v3 08/11] setexpr: rename 'get_arg()' to 'setexpr_get_arg()' lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 09/11] setexpr: Promote 'setexpr_get_arg()' to a public function lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 10/11] setexptr: Extend setexpr_get_arg() to handle pointer to memory lukas.funke-oss
2024-01-10  9:10 ` [PATCH v3 11/11] cmd: printf: forward '%p' format string specifier lukas.funke-oss

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.