From 62f92623b980d034e186bfb7dcb9b6138f953c19 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 24 Aug 2020 09:02:27 +0200 Subject: treewide: s/filed/field/ Fix typos. Signed-off-by: Sascha Hauer --- include/linux/mtd/bbm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 36bb6a503f..1e39883a2d 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -159,7 +159,7 @@ struct bbm_info { int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt); - /* TODO Add more NAND specific fileds */ + /* TODO Add more NAND specific fields */ struct nand_bbt_descr *badblock_pattern; void *priv; -- cgit v1.2.3 From ddcd3d43c1132e5754fa91398dd2138a35660c43 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 14 Sep 2020 12:05:49 +0200 Subject: sandbox: support escaping commas in --image filenames Some tools like afl-fuzz generate file names containing commas. Allow escaping the commas in the file names, so they can be passed to barebox. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/sandbox/os/common.c | 10 ++++++---- include/linux/string.h | 1 + lib/string.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index 9f26f8fa6e..437fe3ecdf 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -212,6 +212,8 @@ int linux_execve(const char * filename, char *const argv[], char *const envp[]) extern void start_barebox(void); extern void mem_malloc_init(void *start, void *end); +extern char * strsep_unescaped(char **s, const char *ct); + static int add_image(char *str, char *devname_template, int *devname_number) { struct hf_info *hf = malloc(sizeof(struct hf_info)); @@ -225,15 +227,15 @@ static int add_image(char *str, char *devname_template, int *devname_number) if (!hf) return -1; - filename = strtok(str, ","); - while ((opt = strtok(NULL, ","))) { + filename = strsep_unescaped(&str, ","); + while ((opt = strsep_unescaped(&str, ","))) { if (!strcmp(opt, "ro")) readonly = 1; } /* parses: "devname=filename" */ - devname = strtok(filename, "="); - filename = strtok(NULL, "="); + devname = strsep_unescaped(&filename, "="); + filename = strsep_unescaped(&filename, "="); if (!filename) { filename = devname; snprintf(tmp, sizeof(tmp), diff --git a/include/linux/string.h b/include/linux/string.h index fd42f5020a..763ef500e5 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -12,6 +12,7 @@ extern char * ___strtok; extern char * strpbrk(const char *,const char *); extern char * strtok(char *,const char *); extern char * strsep(char **,const char *); +extern char * strsep_unescaped(char **,const char *); extern __kernel_size_t strspn(const char *,const char *); diff --git a/lib/string.c b/lib/string.c index 7548fd3581..50f8e2f87c 100644 --- a/lib/string.c +++ b/lib/string.c @@ -455,6 +455,49 @@ char * strsep(char **s, const char *ct) #endif EXPORT_SYMBOL(strsep); +/** + * strsep_unescaped - Split a string into tokens, while ignoring escaped delimiters + * @s: The string to be searched + * @ct: The delimiter characters to search for + * + * strsep_unescaped() behaves like strsep unless it meets an escaped delimiter. + * In that case, it shifts the string back in memory to overwrite the escape's + * backslash then continues the search until an unescaped delimiter is found. + */ +char *strsep_unescaped(char **s, const char *ct) +{ + char *sbegin = *s, *hay; + const char *needle; + size_t shift = 0; + + if (sbegin == NULL) + return NULL; + + for (hay = sbegin; *hay != '\0'; ++hay) { + *hay = hay[shift]; + + if (*hay == '\\') { + *hay = hay[++shift]; + if (*hay != '\\') + continue; + } + + for (needle = ct; *needle != '\0'; ++needle) { + if (*hay == *needle) + goto match; + } + } + + *s = NULL; + return sbegin; + +match: + *hay = '\0'; + *s = &hay[shift + 1]; + + return sbegin; +} + #ifndef __HAVE_ARCH_STRSWAB /** * strswab - swap adjacent even and odd bytes in %NUL-terminated string -- cgit v1.2.3 From 74d78a1e4a47c322d348823b2836614b531cda8b Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 14 Sep 2020 15:37:44 +0200 Subject: lib: string: retire deprecated strtok() in favor of reentrant strsep() With the recent changes to ARCH=sandbox, there are no remaining in-tree users for strtok() anymore. Out-of-tree users are better served by using the reentrant strsep(), which has existed in-tree for as long. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- include/linux/string.h | 2 -- lib/string.c | 35 +++-------------------------------- 2 files changed, 3 insertions(+), 34 deletions(-) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index 763ef500e5..2b699957e8 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -8,9 +8,7 @@ extern "C" { #endif -extern char * ___strtok; extern char * strpbrk(const char *,const char *); -extern char * strtok(char *,const char *); extern char * strsep(char **,const char *); extern char * strsep_unescaped(char **,const char *); extern __kernel_size_t strspn(const char *,const char *); diff --git a/lib/string.c b/lib/string.c index 50f8e2f87c..733b567300 100644 --- a/lib/string.c +++ b/lib/string.c @@ -13,6 +13,9 @@ * * Fri Jun 25 1999, Ingo Oeser * - Added strsep() which will replace strtok() soon (because strsep() is * reentrant and should be faster). Use only strsep() in new code, please. + * * Mon Sep 14 2020, Ahmad Fatoum + * - Kissed strtok() goodbye + * */ #include @@ -20,8 +23,6 @@ #include #include -char * ___strtok; - #ifndef __HAVE_ARCH_STRNICMP /** * strnicmp - Case insensitive, length-limited string comparison @@ -396,36 +397,6 @@ char * strpbrk(const char * cs,const char * ct) #endif EXPORT_SYMBOL(strpbrk); -#ifndef __HAVE_ARCH_STRTOK -/** - * strtok - Split a string into tokens - * @s: The string to be searched - * @ct: The characters to search for - * - * WARNING: strtok is deprecated, use strsep instead. - */ -char * strtok(char * s, const char * ct) -{ - char *sbegin, *send; - - sbegin = s ? s : ___strtok; - if (!sbegin) { - return NULL; - } - sbegin += strspn(sbegin,ct); - if (*sbegin == '\0') { - ___strtok = NULL; - return( NULL ); - } - send = strpbrk( sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - ___strtok = send; - return (sbegin); -} -#endif -EXPORT_SYMBOL(strtok); - #ifndef __HAVE_ARCH_STRSEP /** * strsep - Split a string into tokens -- cgit v1.2.3 From 1c2a23346bd1fa727837bea9be657f4b6f28d53d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 27 Aug 2020 10:43:30 +0200 Subject: clk_dump command: Allow printing a single clock So far the clk_dump command can only print all clocks. With this patch we can limit the output to ancestors and children of a given clock. This makes it easier to find the desired information in big clock trees. Signed-off-by: Sascha Hauer --- commands/clk.c | 15 +++++++++++++-- drivers/clk/clk.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- include/linux/clk.h | 1 + 3 files changed, 59 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/commands/clk.c b/commands/clk.c index 47159dddd2..649a0a7cb2 100644 --- a/commands/clk.c +++ b/commands/clk.c @@ -139,6 +139,7 @@ BAREBOX_CMD_END static int do_clk_dump(int argc, char *argv[]) { int opt, verbose = 0; + struct clk *clk; while ((opt = getopt(argc, argv, "v")) > 0) { switch(opt) { @@ -151,7 +152,16 @@ static int do_clk_dump(int argc, char *argv[]) } } - clk_dump(verbose); + if (optind == argc) { + clk_dump(verbose); + return COMMAND_SUCCESS; + } + + clk = clk_lookup(argv[optind]); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clk_dump_one(clk, verbose); return COMMAND_SUCCESS; } @@ -164,9 +174,10 @@ BAREBOX_CMD_HELP_END BAREBOX_CMD_START(clk_dump) .cmd = do_clk_dump, BAREBOX_CMD_DESC("show information about registered clocks") - BAREBOX_CMD_OPTS("[-v]") + BAREBOX_CMD_OPTS("[-v] [clkname]") BAREBOX_CMD_GROUP(CMD_GRP_INFO) BAREBOX_CMD_HELP(cmd_clk_dump_help) + BAREBOX_CMD_COMPLETE(clk_name_complete) BAREBOX_CMD_END static int do_clk_set_parent(int argc, char *argv[]) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f2e459a760..b04d44593b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -678,7 +678,6 @@ static const char *clk_hw_stat(struct clk *clk) static void dump_one(struct clk *clk, int verbose, int indent) { - struct clk *c; int enabled = clk_is_enabled(clk); const char *hwstat, *stat; @@ -705,13 +704,19 @@ static void dump_one(struct clk *clk, int verbose, int indent) printf("\n"); } } +} + +static void dump_subtree(struct clk *clk, int verbose, int indent) +{ + struct clk *c; + + dump_one(clk, verbose, indent); list_for_each_entry(c, &clks, list) { struct clk *parent = clk_get_parent(c); - if (parent == clk) { - dump_one(c, verbose, indent + 1); - } + if (parent == clk) + dump_subtree(c, verbose, indent + 1); } } @@ -723,7 +728,42 @@ void clk_dump(int verbose) struct clk *parent = clk_get_parent(c); if (IS_ERR_OR_NULL(parent)) - dump_one(c, verbose, 0); + dump_subtree(c, verbose, 0); + } +} + +static int clk_print_parent(struct clk *clk, int verbose) +{ + struct clk *c; + int indent; + + c = clk_get_parent(clk); + if (IS_ERR_OR_NULL(c)) + return 0; + + indent = clk_print_parent(c, verbose); + + dump_one(c, verbose, indent); + + return indent + 1; +} + +void clk_dump_one(struct clk *clk, int verbose) +{ + int indent; + struct clk *c; + + indent = clk_print_parent(clk, verbose); + + printf("\033[1m"); + dump_one(clk, verbose, indent); + printf("\033[0m"); + + list_for_each_entry(c, &clks, list) { + struct clk *parent = clk_get_parent(c); + + if (parent == clk) + dump_subtree(c, verbose, indent + 1); } } diff --git a/include/linux/clk.h b/include/linux/clk.h index 868bf3e4ed..3d66343e8d 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -456,6 +456,7 @@ int clk_register(struct clk *clk); struct clk *clk_lookup(const char *name); void clk_dump(int verbose); +void clk_dump_one(struct clk *clk, int verbose); struct clk *clk_register_composite(const char *name, const char * const *parent_names, int num_parents, -- cgit v1.2.3 From a16f065ae6c17704afe4ed6a4fd3772285a86e6e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 27 Aug 2020 09:26:11 +0200 Subject: clk: Add clk_bulk_[get|put]_all() Signed-off-by: Sascha Hauer --- drivers/clk/clk-bulk.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk.h | 46 +++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) (limited to 'include/linux') diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c index ddbe32f9c2..b8db60dcbc 100644 --- a/drivers/clk/clk-bulk.c +++ b/drivers/clk/clk-bulk.c @@ -53,6 +53,86 @@ err: } EXPORT_SYMBOL(clk_bulk_get); +static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, + struct clk_bulk_data *clks) +{ + int ret; + int i; + + for (i = 0; i < num_clks; i++) { + clks[i].id = NULL; + clks[i].clk = NULL; + } + + for (i = 0; i < num_clks; i++) { + of_property_read_string_index(np, "clock-names", i, &clks[i].id); + clks[i].clk = of_clk_get(np, i); + if (IS_ERR(clks[i].clk)) { + ret = PTR_ERR(clks[i].clk); + pr_err("%pOF: Failed to get clk index: %d ret: %d\n", + np, i, ret); + clks[i].clk = NULL; + goto err; + } + } + + return 0; + +err: + clk_bulk_put(i, clks); + + return ret; +} + +static int __must_check of_clk_bulk_get_all(struct device_node *np, + struct clk_bulk_data **clks) +{ + struct clk_bulk_data *clk_bulk; + int num_clks; + int ret; + + num_clks = of_clk_get_parent_count(np); + if (!num_clks) + return 0; + + clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL); + if (!clk_bulk) + return -ENOMEM; + + ret = of_clk_bulk_get(np, num_clks, clk_bulk); + if (ret) { + kfree(clk_bulk); + return ret; + } + + *clks = clk_bulk; + + return num_clks; +} + +void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) +{ + if (IS_ERR_OR_NULL(clks)) + return; + + clk_bulk_put(num_clks, clks); + + kfree(clks); +} +EXPORT_SYMBOL(clk_bulk_put_all); + +int __must_check clk_bulk_get_all(struct device_d *dev, + struct clk_bulk_data **clks) +{ + struct device_node *np = dev->device_node; + + if (!np) + return 0; + + return of_clk_bulk_get_all(np, clks); +} +EXPORT_SYMBOL(clk_bulk_get_all); + /** * clk_bulk_disable - gate a set of clocks * @num_clks: the number of clk_bulk_data diff --git a/include/linux/clk.h b/include/linux/clk.h index 3d66343e8d..c49fe9a54c 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -82,6 +82,27 @@ struct clk *clk_get(struct device_d *dev, const char *id); int __must_check clk_bulk_get(struct device_d *dev, int num_clks, struct clk_bulk_data *clks); +/** + * clk_bulk_get_all - lookup and obtain all available references to clock + * producer. + * @dev: device for clock "consumer" + * @clks: pointer to the clk_bulk_data table of consumer + * + * This helper function allows drivers to get all clk consumers in one + * operation. If any of the clk cannot be acquired then any clks + * that were obtained will be freed before returning to the caller. + * + * Returns a positive value for the number of clocks obtained while the + * clock references are stored in the clk_bulk_data table in @clks field. + * Returns 0 if there're none and a negative value if something failed. + * + * Drivers must assume that the clock source is not enabled. + * + * clk_bulk_get should not be called from within interrupt context. + */ +int __must_check clk_bulk_get_all(struct device_d *dev, + struct clk_bulk_data **clks); + /** * clk_enable - inform the system when the clock source should be running. * @clk: clock source @@ -156,6 +177,19 @@ unsigned long clk_get_rate(struct clk *clk); */ void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); +/** + * clk_bulk_put_all - "free" all the clock source + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * Note: drivers must ensure that all clk_bulk_enable calls made on this + * clock source are balanced by clk_bulk_disable calls prior to calling + * this function. + * + * clk_bulk_put_all should not be called from within interrupt context. + */ +void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks); + /* * The remaining APIs are optional for machine class support. */ @@ -240,8 +274,16 @@ static inline int __must_check clk_bulk_get(struct device_d *dev, int num_clks, return 0; } +static inline int __must_check clk_bulk_get_all(struct device_d *dev, + struct clk_bulk_data **clks) +{ + return 0; +} + static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} +static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {} + static inline int clk_enable(struct clk *clk) { return 0; @@ -536,6 +578,10 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np, { return ERR_PTR(-ENOENT); } +static inline unsigned int of_clk_get_parent_count(struct device_node *np) +{ + return 0; +} static inline int of_clk_init(struct device_node *root, const struct of_device_id *matches) { -- cgit v1.2.3