summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-07-21 13:52:00 -0600
committerTom Rini <[email protected]>2026-07-21 13:52:00 -0600
commit72d780b5ccc0644f935eb48fdffb92b1177c4fb3 (patch)
tree91cd97e0baf5c6897d020b78193991a94c445cd3
parent85667122fb5fa215315a633335efc27ecd195b21 (diff)
parentd408eb2bc5a4675e11d7b77943553386d039bafc (diff)
Merge patch series "some string cleanup, and a tweak of the "config" command"
Rasmus Villemoes <[email protected]> says: This started by me wanting something like what patch 8 does. That wasn't too hard, except we had no strcasestr(), and also our regex engine (which I didn't really want to pull into the mix anyway) doesn't have a flag that requests case-insensitive matching. So I wanted to add strcasestr(), but then I stumbled on a bunch of stuff that should be cleaned up in str-land. Link: https://lore.kernel.org/r/[email protected]
-rw-r--r--arch/sh/include/asm/string.h51
-rw-r--r--cmd/config.c26
-rw-r--r--doc/usage/cmd/config.rst40
-rw-r--r--include/linux/string.h13
-rw-r--r--lib/string.c70
-rw-r--r--test/cmd/Makefile1
-rw-r--r--test/cmd/config.c28
-rw-r--r--test/lib/string.c24
8 files changed, 146 insertions, 107 deletions
diff --git a/arch/sh/include/asm/string.h b/arch/sh/include/asm/string.h
index 999febcb6b7..12a9a8f796c 100644
--- a/arch/sh/include/asm/string.h
+++ b/arch/sh/include/asm/string.h
@@ -8,8 +8,6 @@
* from linux kernel code.
*/
-#ifdef __KERNEL__ /* only set these up for kernel code */
-
#define __HAVE_ARCH_STRCPY
static inline char *strcpy(char *__dest, const char *__src)
{
@@ -81,53 +79,4 @@ static inline int strcmp(const char *__cs, const char *__ct)
return __res;
}
-#undef __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *__cs, const char *__ct, size_t __n);
-
-#undef __HAVE_ARCH_MEMSET
-extern void *memset(void *__s, int __c, size_t __count);
-
-#undef __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
-
-#undef __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
-
-#undef __HAVE_ARCH_MEMCHR
-extern void *memchr(const void *__s, int __c, size_t __n);
-
-#undef __HAVE_ARCH_STRLEN
-extern size_t strlen(const char *);
-
-/* arch/sh/lib/strcasecmp.c */
-extern int strcasecmp(const char *, const char *);
-
-#else /* KERNEL */
-
-/*
- * let user libraries deal with these,
- * IMHO the kernel has no place defining these functions for user apps
- */
-
-#define __HAVE_ARCH_STRCPY 1
-#define __HAVE_ARCH_STRNCPY 1
-#define __HAVE_ARCH_STRCAT 1
-#define __HAVE_ARCH_STRNCAT 1
-#define __HAVE_ARCH_STRCMP 1
-#define __HAVE_ARCH_STRNCMP 1
-#define __HAVE_ARCH_STRNICMP 1
-#define __HAVE_ARCH_STRCHR 1
-#define __HAVE_ARCH_STRRCHR 1
-#define __HAVE_ARCH_STRSTR 1
-#define __HAVE_ARCH_STRLEN 1
-#define __HAVE_ARCH_STRNLEN 1
-#define __HAVE_ARCH_MEMSET 1
-#define __HAVE_ARCH_MEMCPY 1
-#define __HAVE_ARCH_MEMMOVE 1
-#define __HAVE_ARCH_MEMSCAN 1
-#define __HAVE_ARCH_MEMCMP 1
-#define __HAVE_ARCH_MEMCHR 1
-#define __HAVE_ARCH_STRTOK 1
-
-#endif /* KERNEL */
#endif /* __ASM_SH_STRING_H */
diff --git a/cmd/config.c b/cmd/config.c
index f0d2033c61f..22115e9b1da 100644
--- a/cmd/config.c
+++ b/cmd/config.c
@@ -6,6 +6,7 @@
#include <command.h>
#include <gzip.h>
#include <malloc.h>
+#include <linux/string.h>
#include "config_data_gz.h"
#include "config_data_size.h"
@@ -29,7 +30,23 @@ static int do_config(struct cmd_tbl *cmdtp, int flag, int argc,
}
dst[data_size] = 0;
- puts(dst);
+ if (argc > 1) {
+ const char *s = argv[1];
+ char *b = dst, *e = dst + data_size, *n;
+
+ while (b < e) {
+ n = strchrnul(b, '\n');
+ *n = '\0';
+
+ if (strcasestr(b, s)) {
+ puts(b);
+ puts("\n");
+ }
+ b = n + 1;
+ }
+ } else {
+ puts(dst);
+ }
free:
free(dst);
@@ -38,7 +55,10 @@ free:
}
U_BOOT_CMD(
- config, 1, 1, do_config,
+ config, 2, 1, do_config,
"print .config",
- ""
+ "[str]\n"
+ "\n"
+ "When the optional argument is given, only lines containing\n"
+ "that string are printed. Matching is case-insensitive."
);
diff --git a/doc/usage/cmd/config.rst b/doc/usage/cmd/config.rst
new file mode 100644
index 00000000000..bd8aa65ddbc
--- /dev/null
+++ b/doc/usage/cmd/config.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. index::
+ single: config (command)
+
+config command
+==============
+
+Synopsis
+--------
+
+::
+
+ config [<str>]
+
+Description
+-----------
+
+The config command prints the `.config` file used when building U-Boot
+to the console. Note that the `.config` file is usually several 1000
+lines long.
+
+If the optional argument is given, only lines containing that string
+(case insensitively) are printed. That can be useful if one wants to
+check whether a specific option is enabled, or just to limit the
+output to the subsystem of interest.
+
+The `.config` file is stored inside the U-Boot binary in
+gzip-compressed format.
+
+Examples
+--------
+
+.. code-block:: bash
+
+ # Print the entire .config
+ config
+
+ # Print all lines related to pinctrl
+ config pinctrl
diff --git a/include/linux/string.h b/include/linux/string.h
index 850356d7c3f..986499dfc70 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -43,12 +43,8 @@ extern int strcmp(const char *,const char *);
#ifndef __HAVE_ARCH_STRNCMP
extern int strncmp(const char *,const char *,__kernel_size_t);
#endif
-#ifndef __HAVE_ARCH_STRCASECMP
int strcasecmp(const char *s1, const char *s2);
-#endif
-#ifndef __HAVE_ARCH_STRNCASECMP
-extern int strncasecmp(const char *s1, const char *s2, __kernel_size_t len);
-#endif
+int strncasecmp(const char *s1, const char *s2, __kernel_size_t len);
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
@@ -63,7 +59,7 @@ extern char * strchr(const char *,int);
* @c: character to search for
* Return: position of @c in @s, or end of @s if not found
*/
-const char *strchrnul(const char *s, int c);
+char *strchrnul(const char *s, int c);
#ifndef __HAVE_ARCH_STRRCHR
extern char * strrchr(const char *,int);
@@ -75,6 +71,7 @@ extern char * strstr(const char *,const char *);
#ifndef __HAVE_ARCH_STRNSTR
extern char *strnstr(const char *, const char *, size_t);
#endif
+char *strcasestr(const char *, const char *);
#ifndef __HAVE_ARCH_STRLEN
extern __kernel_size_t strlen(const char *);
#endif
@@ -107,10 +104,6 @@ extern char * strndup(const char *, size_t);
extern const char *strdup_const(const char *s);
extern void kfree_const(const void *x);
-#ifndef __HAVE_ARCH_STRSWAB
-extern char * strswab(const char *);
-#endif
-
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
#endif
diff --git a/lib/string.c b/lib/string.c
index 37ea8c29561..dbf2ce340df 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -263,12 +263,12 @@ char * strchr(const char * s, int c)
}
#endif
-const char *strchrnul(const char *s, int c)
+char *strchrnul(const char *s, int c)
{
for (; *s != (char)c; ++s)
if (*s == '\0')
break;
- return s;
+ return (char *)s;
}
#ifndef __HAVE_ARCH_STRRCHR
@@ -399,7 +399,6 @@ void kfree_const(const void *x)
}
-#ifndef __HAVE_ARCH_STRSPN
/**
* strspn - Calculate the length of the initial substring of @s which only
* contain letters in @accept
@@ -424,9 +423,7 @@ size_t strspn(const char *s, const char *accept)
return count;
}
-#endif
-#ifndef __HAVE_ARCH_STRPBRK
/**
* strpbrk - Find the first occurrence of a set of characters
* @cs: The string to be searched
@@ -444,9 +441,7 @@ char * strpbrk(const char * cs,const char * ct)
}
return NULL;
}
-#endif
-#ifndef __HAVE_ARCH_STRTOK
/**
* strtok - Split a string into tokens
* @s: The string to be searched
@@ -473,9 +468,7 @@ char * strtok(char * s,const char * ct)
___strtok = send;
return (sbegin);
}
-#endif
-#ifndef __HAVE_ARCH_STRSEP
/**
* strsep - Split a string into tokens
* @s: The string to be searched
@@ -501,35 +494,6 @@ char * strsep(char **s, const char *ct)
return sbegin;
}
-#endif
-
-#ifndef __HAVE_ARCH_STRSWAB
-/**
- * strswab - swap adjacent even and odd bytes in %NUL-terminated string
- * s: address of the string
- *
- * returns the address of the swapped string or NULL on error. If
- * string length is odd, last byte is untouched.
- */
-char *strswab(const char *s)
-{
- char *p, *q;
-
- if ((NULL == s) || ('\0' == *s)) {
- return (NULL);
- }
-
- for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) {
- char tmp;
-
- tmp = *p;
- *p = *q;
- *q = tmp;
- }
-
- return (char *) s;
-}
-#endif
#ifndef __HAVE_ARCH_MEMSET
/**
@@ -702,7 +666,7 @@ void *memdup(const void *src, size_t len)
*
* @s1: string to be searched
* @s2: string to search for
- * @len: maximum number of characters in s2 to consider
+ * @len: maximum number of characters in s1 to consider
*
* Return: pointer to the first occurrence or NULL
*/
@@ -728,7 +692,6 @@ char *strnstr(const char *s1, const char *s2, size_t len)
*
* @s1: string to be searched
* @s2: string to search for
- * @len: maximum number of characters in s2 to consider
*
* Return: pointer to the first occurrence or NULL
*/
@@ -738,6 +701,33 @@ char *strstr(const char *s1, const char *s2)
}
#endif
+/**
+ * strcasestr() - Case insensitive substring search
+ *
+ * @haystack: string to be searched
+ * @needle: string to search for
+ *
+ * Return: pointer to the first occurrence or NULL
+ *
+ * The case of both strings are ignored.
+ */
+char *strcasestr(const char *haystack, const char *needle)
+{
+ size_t l1, l2;
+
+ l1 = strlen(haystack);
+ l2 = strlen(needle);
+
+ while (l1 >= l2) {
+ if (!strncasecmp(haystack, needle, l2))
+ return (char *)haystack;
+ haystack++;
+ l1--;
+ }
+
+ return NULL;
+}
+
#ifndef __HAVE_ARCH_MEMCHR
/**
* memchr - Find a character in an area of memory.
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 8d6932f1176..8d36463879d 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -17,6 +17,7 @@ ifdef CONFIG_CONSOLE_RECORD
obj-$(CONFIG_CMD_ACPI) += acpi.o
endif
obj-$(CONFIG_CMD_BDI) += bdinfo.o
+obj-$(CONFIG_CMD_CONFIG) += config.o
obj-$(CONFIG_COREBOOT_SYSINFO) += coreboot.o
obj-$(CONFIG_CMD_FDT) += fdt.o
obj-$(CONFIG_CMD_HASH) += hash.o
diff --git a/test/cmd/config.c b/test/cmd/config.c
new file mode 100644
index 00000000000..5a48060801f
--- /dev/null
+++ b/test/cmd/config.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Tests for config command
+ */
+
+#include <console.h>
+#include <test/cmd.h>
+#include <test/ut.h>
+
+static int cmd_test_config(struct unit_test_state *uts)
+{
+ ut_assertok(run_command("config", 0));
+ ut_assert_skip_to_line("# Automatically generated file; DO NOT EDIT.");
+ ut_assert_skip_to_linen("# Compiler:");
+ ut_assert_skip_to_line("CONFIG_CMD_CONFIG=y");
+
+ console_record_reset_enable();
+
+ ut_assertok(run_command("config cmd_config=y", 0));
+ ut_assert_nextline("CONFIG_CMD_CONFIG=y");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("config 'this string never appears in .config'", 0));
+ ut_assert_console_end();
+
+ return 0;
+}
+CMD_TEST(cmd_test_config, UTF_CONSOLE);
diff --git a/test/lib/string.c b/test/lib/string.c
index db6f28dbfdf..d418a40c4d4 100644
--- a/test/lib/string.c
+++ b/test/lib/string.c
@@ -284,18 +284,36 @@ static int lib_strstr(struct unit_test_state *uts)
{
const char *s1 = "Itsy Bitsy Teenie Weenie";
const char *s2 = "eenie";
- const char *s3 = "easy";
+ const char *s3 = "bits";
ut_asserteq_ptr(&s1[12], strstr(s1, s2));
ut_asserteq_ptr(&s1[13], strstr(&s1[3], &s2[1]));
ut_assertnull(strstr(s1, s3));
- ut_asserteq_ptr(&s1[2], strstr(s1, &s3[2]));
- ut_asserteq_ptr(&s1[8], strstr(&s1[5], &s3[2]));
+ ut_asserteq_ptr(&s1[1], strstr(s1, &s3[2]));
+ ut_asserteq_ptr(&s1[7], strstr(&s1[5], &s3[2]));
return 0;
}
LIB_TEST(lib_strstr, 0);
+/** lib_strcasestr() - unit test for strcasestr() */
+static int lib_strcasestr(struct unit_test_state *uts)
+{
+ const char *s1 = "Itsy Bitsy Teenie Weenie";
+ const char *s2 = "eenie";
+ const char *s3 = "bits";
+
+ ut_asserteq_ptr(&s1[12], strcasestr(s1, s2));
+ ut_asserteq_ptr(&s1[13], strcasestr(&s1[3], &s2[1]));
+ ut_asserteq_ptr(&s1[5], strcasestr(s1, s3));
+ ut_asserteq_ptr(&s1[1], strcasestr(s1, &s3[2]));
+ ut_asserteq_ptr(&s1[7], strcasestr(&s1[5], &s3[2]));
+ ut_assertnull(strcasestr(&s1[6], s3));
+
+ return 0;
+}
+LIB_TEST(lib_strcasestr, 0);
+
static int lib_strim(struct unit_test_state *uts)
{
char buf[BUFLEN], *p;