All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] [RFC] kconfig: new command line tool to set configs
@ 2020-05-06 12:52 Jukka Kaartinen
  2020-05-06 12:52 ` [PATCH 1/2] kconfig: a " Jukka Kaartinen
  2020-05-06 12:52 ` [PATCH 2/2] kconfig: Extend kconfig with setall option Jukka Kaartinen
  0 siblings, 2 replies; 4+ messages in thread
From: Jukka Kaartinen @ 2020-05-06 12:52 UTC (permalink / raw)
  To: linux-kbuild
  Cc: yamada.masahiro, lukas.bulwahn, jouni.hogander, dan.carpenter,
	Jukka Kaartinen

From: Jukka Kaartinen <jukka.kaartinen@partner.bmw.de>

Me, Jouni Högander and Lukas Bulwahn are working on to improve
syzkaller with configuration bisect
feature: https://github.com/google/syzkaller/pull/1689
For that we need to set kernel configurations without human
interaction.
Currently there are no tools to set config options on if it has 
dependencies without human interaction if dependencies are not known beforehand.

I found this old patch from Dan Carpenter 
https://patchwork.kernel.org/patch/6387181/ that can handle the 
dependencies using only commandline and with a small feature added 
it can be automated to say "yes" to all dependencies.

Dan Carpenter (1):
  kconfig: a new command line tool to set configs

Jukka Kaartinen (1):
  kconfig: Extend kconfig with setall option

 scripts/kconfig/Makefile |   7 +
 scripts/kconfig/kconfig  |  83 ++++++++++
 scripts/kconfig/lconf.c  | 328 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 418 insertions(+)
 create mode 100755 scripts/kconfig/kconfig
 create mode 100644 scripts/kconfig/lconf.c

-- 
2.17.1

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

* [PATCH 1/2] kconfig: a new command line tool to set configs
  2020-05-06 12:52 [PATCH 0/2] [RFC] kconfig: new command line tool to set configs Jukka Kaartinen
@ 2020-05-06 12:52 ` Jukka Kaartinen
  2020-05-06 12:52 ` [PATCH 2/2] kconfig: Extend kconfig with setall option Jukka Kaartinen
  1 sibling, 0 replies; 4+ messages in thread
From: Jukka Kaartinen @ 2020-05-06 12:52 UTC (permalink / raw)
  To: linux-kbuild
  Cc: yamada.masahiro, lukas.bulwahn, jouni.hogander, dan.carpenter,
	Jukka Kaartinen

From: Dan Carpenter <dan.carpenter@oracle.com>

This is an ugly hack job I made last night and it barely works.  It
does two things:

1)  Sometimes I want to search for a config so I have to load
    menuconfig, then search for the config entry, then exit.  With
    this script I simply run:

	./scripts/kconfig/kconfig search COMEDI

2)  I quite often try to enable something by doing:

	echo CONFIG_FOO=y >> .config
	make oldconfig
	grep CONFIG_FOO .config

    The grep is to see if the setting worked.  Now I can do:

	./scripts/kconfig/kconfig set CONFIG_FOO=y

Parsing dependencies barely works, but that's just a matter of writing
some more code in expr_parse().

The main questions I have at this point are:

1)  If I have a symbol pointer, is it possible to get a help text from
    that?

2)  For some reason, when I do sym_set_tristate_value() it doesn't
    actually set anything until I write the config file so I have to do:

		if (sym_set_tristate_value(sym, newval)) {
			/* FIXME: if I don't write it doesn't save */
			conf_write(NULL);
			return 1;
		}

    It makes the output really messy.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Jukka Kaartinen <jukka.kaartinen@unikie.com>
---
 scripts/kconfig/Makefile |   7 +
 scripts/kconfig/kconfig  |  34 +++++
 scripts/kconfig/lconf.c  | 312 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 353 insertions(+)
 create mode 100755 scripts/kconfig/kconfig
 create mode 100644 scripts/kconfig/lconf.c

diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 2f1a59fa5169..62af9f29b5e1 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -38,6 +38,9 @@ config: $(obj)/conf
 nconfig: $(obj)/nconf
 	$< $(silent) $(Kconfig)
 
+lconfig: $(obj)/lconf
+	$< $(silent) $(Kconfig)
+
 build_menuconfig: $(obj)/mconf
 
 build_nconfig: $(obj)/nconf
@@ -200,6 +203,10 @@ $(obj)/%.moc: $(src)/%.h $(obj)/qconf-cfg
 hostprogs-y	+= gconf
 gconf-objs	:= gconf.o images.o $(common-objs)
 
+# lconf: Used to search and turn on configs from commandline
+hostprogs-y	+= lconf
+lconf-objs	:= lconf.o $(common-objs)
+
 HOSTLDLIBS_gconf    = $(shell . $(obj)/gconf-cfg && echo $$libs)
 HOSTCFLAGS_gconf.o  = $(shell . $(obj)/gconf-cfg && echo $$cflags)
 
diff --git a/scripts/kconfig/kconfig b/scripts/kconfig/kconfig
new file mode 100755
index 000000000000..2762c8dc04a8
--- /dev/null
+++ b/scripts/kconfig/kconfig
@@ -0,0 +1,34 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+usage() {
+	echo "kconfig [search|set] string"
+	exit 1;
+}
+
+if [ "$1" = "" ] ; then
+	usage
+fi
+
+if [ "$1" = "search" ] ; then
+
+	search=$2
+	NCONFIG_MODE=kconfig_search SEARCH=${search} make lconfig
+
+elif [ "$1" = "set" ] ; then
+
+	config=$2
+	setting=$3
+
+	if [ $config = "" ] ; then
+		echo "nothing to set"
+		exit 1
+	fi
+
+	NCONFIG_MODE=kconfig_set CONFIG=${config} SETTING=${setting} make lconfig
+
+else
+	usage
+fi
+
+
diff --git a/scripts/kconfig/lconf.c b/scripts/kconfig/lconf.c
new file mode 100644
index 000000000000..cde717f36eb1
--- /dev/null
+++ b/scripts/kconfig/lconf.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015 Oracle
+ */
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "nconf.h"
+#include <ctype.h>
+#include <locale.h>
+#include <libintl.h>
+
+static int indent;
+static char line[128];
+
+static int get_depends(struct symbol *sym);
+
+static void strip(char *str)
+{
+	char *p = str;
+	int l;
+
+	while ((isspace(*p)))
+		p++;
+	l = strlen(p);
+	if (p != str)
+		memmove(str, p, l + 1);
+	if (!l)
+		return;
+	p = str + l - 1;
+	while ((isspace(*p)))
+		*p-- = 0;
+}
+
+static void xfgets(char *str, int size, FILE *in)
+{
+	if (fgets(str, size, in) == NULL)
+		fprintf(stderr, "\nError in reading or end of file.\n");
+}
+
+static int conf_askvalue(struct symbol *sym, const char *def)
+{
+	enum symbol_type type = sym_get_type(sym);
+
+	if (!sym_has_value(sym))
+		printf("(NEW) ");
+
+	line[0] = '\n';
+	line[1] = 0;
+
+	if (!sym_is_changeable(sym)) {
+		printf("%s\n", def);
+		line[0] = '\n';
+		line[1] = 0;
+		return 0;
+	}
+
+	fflush(stdout);
+	xfgets(line, 128, stdin);
+
+	switch (type) {
+	case S_INT:
+	case S_HEX:
+	case S_STRING:
+		printf("%s\n", def);
+		return 1;
+	default:
+		break;
+	}
+	printf("%s", line);
+	return 1;
+}
+
+static struct property *get_symbol_prop(struct symbol *sym)
+{
+	struct property *prop = NULL;
+
+	for_all_properties(sym, prop, P_SYMBOL)
+		break;
+	return prop;
+}
+
+static int conf_sym(struct symbol *sym)
+{
+	tristate oldval, newval;
+	struct property *prop;
+
+	while (1) {
+		if (sym->name)
+			printf("%s: ", sym->name);
+		for_all_prompts(sym, prop)
+			printf("%*s%s ", indent - 1, "",  prop->text);
+		putchar('[');
+		oldval = sym_get_tristate_value(sym);
+		switch (oldval) {
+		case no:
+			putchar('N');
+			break;
+		case mod:
+			putchar('M');
+			break;
+		case yes:
+			putchar('Y');
+			break;
+		}
+		if (oldval != no && sym_tristate_within_range(sym, no))
+			printf("/n");
+		if (oldval != mod && sym_tristate_within_range(sym, mod))
+			printf("/m");
+		if (oldval != yes && sym_tristate_within_range(sym, yes))
+			printf("/y");
+		/* FIXME: I don't know how to get the help text from the sym */
+		printf("] ");
+		if (!conf_askvalue(sym, sym_get_string_value(sym)))
+			return 0;
+		strip(line);
+
+		switch (line[0]) {
+		case 'n':
+		case 'N':
+			newval = no;
+			if (!line[1] || !strcmp(&line[1], "o"))
+				break;
+			continue;
+		case 'm':
+		case 'M':
+			newval = mod;
+			if (!line[1])
+				break;
+			continue;
+		case 'y':
+		case 'Y':
+			newval = yes;
+			if (!line[1] || !strcmp(&line[1], "es"))
+				break;
+			continue;
+		case 0:
+			newval = oldval;
+			break;
+		default:
+			continue;
+		}
+		if (sym_set_tristate_value(sym, newval)) {
+			/* FIXME: if I don't write it doesn't save */
+			conf_write(NULL);
+			return 1;
+		}
+	}
+}
+
+static int enable_sym(struct symbol *sym)
+{
+	if (sym_get_tristate_value(sym) != no)
+		return 0;
+
+	if (!sym->visible) {
+		printf("%s: has missing dependencies\n", sym->name);
+		if (!get_depends(sym))
+			return 0;
+	}
+
+	return conf_sym(sym);
+}
+
+static void expr_parse(struct expr *e)
+{
+	if (!e)
+		return;
+
+	switch (e->type) {
+	case E_EQUAL:
+		printf("set '%s' to '%s'\n",
+			e->left.sym->name, e->right.sym->name);
+		break;
+
+	case E_AND:
+		expr_parse(e->left.expr);
+		expr_parse(e->right.expr);
+		break;
+
+	case E_SYMBOL:
+		enable_sym(e->left.sym);
+		break;
+
+	case E_NOT:
+	case E_UNEQUAL:
+	case E_OR:
+	case E_LIST:
+	case E_RANGE:
+	default:
+		printf("HELP.  Lot of unimplemented code\n");
+		break;
+	}
+}
+
+static int get_depends(struct symbol *sym)
+{
+	struct property *prop;
+	struct gstr res = str_new();
+
+	prop = get_symbol_prop(sym);
+	if (!prop)
+		return 0;
+
+	expr_gstr_print(prop->visible.expr, &res);
+	printf("%s\n\n", str_get(&res));
+
+	expr_parse(prop->visible.expr);
+
+	return 1;
+}
+
+static void kconfig_search(void)
+{
+	char *search_str;
+	struct symbol **sym_arr;
+	struct gstr res;
+
+	search_str = getenv("SEARCH");
+	if (!search_str)
+		return;
+
+	sym_arr = sym_re_search(search_str);
+	res = get_relations_str(sym_arr, NULL);
+	printf("%s", str_get(&res));
+}
+
+static void kconfig_set(void)
+{
+	struct symbol *sym;
+	char *config;
+	char *setting;
+	int res;
+
+	config = getenv("CONFIG");
+	if (!config)
+		return;
+	if (strncmp(config, "CONFIG_", 7) == 0)
+		config += 7;
+
+	setting = strchr(config, '=');
+	if (setting) {
+		*setting = '\0';
+		setting++;
+	} else {
+		setting = getenv("SETTING");
+		if (setting && *setting == '\0')
+			setting = NULL;
+	}
+
+	sym = sym_find(config);
+	if (!sym) {
+		printf("Error: '%s' not found.\n", config);
+		return;
+	}
+
+	if (!sym->visible) {
+		printf("\n%s: has missing dependencies\n", sym->name);
+		if (!get_depends(sym))
+			return;
+	}
+	if (!sym->visible) {
+		printf("Error: unmet dependencies\n");
+		return;
+	}
+
+	if (!setting) {
+		conf_sym(sym);
+	} else if (!sym_set_string_value(sym, setting)) {
+		printf("Error: setting '%s=%s' failed.\n", sym->name, setting);
+		return;
+	}
+
+	res = conf_write(NULL);
+	if (res) {
+		printf("Error during writing of configuration.\n"
+			"Your configuration changes were NOT saved.\n");
+		return;
+	}
+
+	printf("set: %s=%s\n", config, sym_get_string_value(sym));
+}
+
+int main(int ac, char **av)
+{
+	char *mode;
+
+	if (ac > 1 && strcmp(av[1], "-s") == 0) {
+		/* Silence conf_read() until the real callback is set up */
+		conf_set_message_callback(NULL);
+		av++;
+	}
+	conf_parse(av[1]);
+	conf_read(NULL);
+
+	mode = getenv("NCONFIG_MODE");
+	if (!mode)
+		return 1;
+
+	if (strcmp(mode, "kconfig_search") == 0) {
+		kconfig_search();
+		return 0;
+	}
+	if (strcmp(mode, "kconfig_set") == 0) {
+		kconfig_set();
+		return 0;
+	}
+
+	return 1;
+}
-- 
2.17.1

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

* [PATCH 2/2] kconfig: Extend kconfig with setall option
  2020-05-06 12:52 [PATCH 0/2] [RFC] kconfig: new command line tool to set configs Jukka Kaartinen
  2020-05-06 12:52 ` [PATCH 1/2] kconfig: a " Jukka Kaartinen
@ 2020-05-06 12:52 ` Jukka Kaartinen
  2020-05-07  6:16   ` [PATCH v2] " Jukka Kaartinen
  1 sibling, 1 reply; 4+ messages in thread
From: Jukka Kaartinen @ 2020-05-06 12:52 UTC (permalink / raw)
  To: linux-kbuild
  Cc: yamada.masahiro, lukas.bulwahn, jouni.hogander, dan.carpenter,
	Jukka Kaartinen

setall will set all possible dependencies automatically to
value "y".

Signed-off-by: Jukka Kaartinen <jukka.kaartinen@unikie.com>
---
 scripts/kconfig/kconfig | 75 ++++++++++++++++++++++++++++++++++-------
 scripts/kconfig/lconf.c | 16 +++++++++
 2 files changed, 78 insertions(+), 13 deletions(-)

diff --git a/scripts/kconfig/kconfig b/scripts/kconfig/kconfig
index 2762c8dc04a8..0546ad5a44c1 100755
--- a/scripts/kconfig/kconfig
+++ b/scripts/kconfig/kconfig
@@ -2,33 +2,82 @@
 # SPDX-License-Identifier: GPL-2.0
 
 usage() {
-	echo "kconfig [search|set] string"
+	echo "kconfig [search|set|setall|val|out] string"
+	echo "      search         Search config option"
+	echo "      set            Config option"
+	echo "      setall         Set all possible dependencies to 'y'"
+	echo "      val            Value for config option"
+	echo "      out            Directory for O=<out>"
+	echo ""
+	echo " example:"
+	echo "   $0 set I2C val y"
 	exit 1;
 }
 
-if [ "$1" = "" ] ; then
-	usage
-fi
+search=""
+search_val=""
+config=""
+config_val=""
+output=""
+setting=""
+
+while [[ $# -gt 0 ]]
+do
+	key="$1"
+	case $key in
+		search)
+			search=1
+			search_val="$2"
+			shift # past argument
+			shift # past value
+			;;
+		set)
+			config=1
+			config_val="$2"
+			shift # past argument
+			shift # past value
+			;;
+		setall)
+			all="y"
+			shift # past argument
+			;;
+		val)
+			setting="$2"
+			shift # past argument
+			shift # past value
+			;;
+		out)
+			output="O=$2"
+			shift # past argument
+			shift # past value
+			;;
+		*)    # unknown option
+			echo "Unknown option: $1"
+			usage
+			exit 1
+			;;
+	esac
+done
 
-if [ "$1" = "search" ] ; then
+if [ "$search" != "" ] ; then
 
-	search=$2
-	NCONFIG_MODE=kconfig_search SEARCH=${search} make lconfig
+	if [ $search_val = "" ] ; then
+		echo "nothing to search"
+		exit 1
+	fi
 
-elif [ "$1" = "set" ] ; then
+	NCONFIG_MODE=kconfig_search SEARCH=${search_val} make lconfig ${output}
 
-	config=$2
-	setting=$3
+elif [ "$config" != "" ] ; then
 
-	if [ $config = "" ] ; then
+	if [ $config_val = "" ] ; then
 		echo "nothing to set"
 		exit 1
 	fi
 
-	NCONFIG_MODE=kconfig_set CONFIG=${config} SETTING=${setting} make lconfig
+	ALLYES=${all} NCONFIG_MODE=kconfig_set CONFIG=${config_val} SETTING=${setting} make lconfig ${output}
 
 else
 	usage
 fi
 
-
diff --git a/scripts/kconfig/lconf.c b/scripts/kconfig/lconf.c
index cde717f36eb1..b8634f8f662d 100644
--- a/scripts/kconfig/lconf.c
+++ b/scripts/kconfig/lconf.c
@@ -14,6 +14,7 @@
 
 static int indent;
 static char line[128];
+static char *ask_from_user;
 
 static int get_depends(struct symbol *sym);
 
@@ -57,6 +58,12 @@ static int conf_askvalue(struct symbol *sym, const char *def)
 		return 0;
 	}
 
+	if (ask_from_user) {
+		line[0] = 'y';
+		line[1] = '\0';
+		return 0;
+	}
+
 	fflush(stdout);
 	xfgets(line, 128, stdin);
 
@@ -232,8 +239,17 @@ static void kconfig_set(void)
 	struct symbol *sym;
 	char *config;
 	char *setting;
+	char *allyes;
 	int res;
 
+	allyes = getenv("ALLYES");
+	if (allyes) {
+		if (strncmp(allyes, "y", 1) == 0) {
+			ask_from_user = "y";
+			printf("Set all dependencies to yes.\n");
+		}
+	}
+
 	config = getenv("CONFIG");
 	if (!config)
 		return;
-- 
2.17.1

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

* [PATCH v2] kconfig: Extend kconfig with setall option
  2020-05-06 12:52 ` [PATCH 2/2] kconfig: Extend kconfig with setall option Jukka Kaartinen
@ 2020-05-07  6:16   ` Jukka Kaartinen
  0 siblings, 0 replies; 4+ messages in thread
From: Jukka Kaartinen @ 2020-05-07  6:16 UTC (permalink / raw)
  To: linux-kbuild
  Cc: yamada.masahiro, lukas.bulwahn, jouni.hogander, dan.carpenter,
	Jukka Kaartinen

setall will set all possible dependencies automatically to
value "y".

Signed-off-by: Jukka Kaartinen <jukka.kaartinen@unikie.com>
---
 scripts/kconfig/kconfig | 77 +++++++++++++++++++++++++++++++++--------
 scripts/kconfig/lconf.c | 16 +++++++++
 2 files changed, 79 insertions(+), 14 deletions(-)

diff --git a/scripts/kconfig/kconfig b/scripts/kconfig/kconfig
index 2762c8dc04a8..7dd7bca2e0e8 100755
--- a/scripts/kconfig/kconfig
+++ b/scripts/kconfig/kconfig
@@ -1,34 +1,83 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
 usage() {
-	echo "kconfig [search|set] string"
+	echo "kconfig [search|set|setall|val|out] string"
+	echo "      search         Search config option"
+	echo "      set            Config option"
+	echo "      setall         Set all possible dependencies to 'y'"
+	echo "      val            Value for config option"
+	echo "      out            Directory for O=<out>"
+	echo ""
+	echo " example:"
+	echo "   $0 set I2C val y"
 	exit 1;
 }
 
-if [ "$1" = "" ] ; then
-	usage
-fi
+search=""
+search_val=""
+config=""
+config_val=""
+output=""
+setting=""
+
+while [[ $# -gt 0 ]]
+do
+	key="$1"
+	case $key in
+		search)
+			search=1
+			search_val="$2"
+			shift # past argument
+			shift # past value
+			;;
+		set)
+			config=1
+			config_val="$2"
+			shift # past argument
+			shift # past value
+			;;
+		setall)
+			all="y"
+			shift # past argument
+			;;
+		val)
+			setting="$2"
+			shift # past argument
+			shift # past value
+			;;
+		out)
+			output="O=$2"
+			shift # past argument
+			shift # past value
+			;;
+		*)    # unknown option
+			echo "Unknown option: $1"
+			usage
+			exit 1
+			;;
+	esac
+done
 
-if [ "$1" = "search" ] ; then
+if [ "$search" != "" ] ; then
 
-	search=$2
-	NCONFIG_MODE=kconfig_search SEARCH=${search} make lconfig
+	if [ $search_val = "" ] ; then
+		echo "nothing to search"
+		exit 1
+	fi
 
-elif [ "$1" = "set" ] ; then
+	NCONFIG_MODE=kconfig_search SEARCH=${search_val} make lconfig ${output}
 
-	config=$2
-	setting=$3
+elif [ "$config" != "" ] ; then
 
-	if [ $config = "" ] ; then
+	if [ $config_val = "" ] ; then
 		echo "nothing to set"
 		exit 1
 	fi
 
-	NCONFIG_MODE=kconfig_set CONFIG=${config} SETTING=${setting} make lconfig
+	ALLYES=${all} NCONFIG_MODE=kconfig_set CONFIG=${config_val} SETTING=${setting} make lconfig ${output}
 
 else
 	usage
 fi
 
-
diff --git a/scripts/kconfig/lconf.c b/scripts/kconfig/lconf.c
index cde717f36eb1..b8634f8f662d 100644
--- a/scripts/kconfig/lconf.c
+++ b/scripts/kconfig/lconf.c
@@ -14,6 +14,7 @@
 
 static int indent;
 static char line[128];
+static char *ask_from_user;
 
 static int get_depends(struct symbol *sym);
 
@@ -57,6 +58,12 @@ static int conf_askvalue(struct symbol *sym, const char *def)
 		return 0;
 	}
 
+	if (ask_from_user) {
+		line[0] = 'y';
+		line[1] = '\0';
+		return 0;
+	}
+
 	fflush(stdout);
 	xfgets(line, 128, stdin);
 
@@ -232,8 +239,17 @@ static void kconfig_set(void)
 	struct symbol *sym;
 	char *config;
 	char *setting;
+	char *allyes;
 	int res;
 
+	allyes = getenv("ALLYES");
+	if (allyes) {
+		if (strncmp(allyes, "y", 1) == 0) {
+			ask_from_user = "y";
+			printf("Set all dependencies to yes.\n");
+		}
+	}
+
 	config = getenv("CONFIG");
 	if (!config)
 		return;
-- 
2.17.1

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

end of thread, other threads:[~2020-05-07  6:16 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-06 12:52 [PATCH 0/2] [RFC] kconfig: new command line tool to set configs Jukka Kaartinen
2020-05-06 12:52 ` [PATCH 1/2] kconfig: a " Jukka Kaartinen
2020-05-06 12:52 ` [PATCH 2/2] kconfig: Extend kconfig with setall option Jukka Kaartinen
2020-05-07  6:16   ` [PATCH v2] " Jukka Kaartinen

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.