[PATCH 21/32] kconfig: Support writing separate SPL files

Simon Glass sjg at chromium.org
Tue Jan 31 16:26:51 CET 2023


At present kconfig writes out several files, including:

   auto.conf  - CONFIG settings used by make
   autoconf.h - header file used by C code

This works well but is a bit ugly in places, for example requiring the use
of a SPL_TPL_ macro in Makefiles to distinguish between options intended
for SPL and U-Boot proper.

Update the kconfig tool to also output separate files for each phase: e.g.
auto_spl.conf and autoconf_spl.h

These are similar to the existing file, but drop the SPL_ prefix so that
SPL_TPL_ is not needed. It also allows the CONFIG_IS_ENABLED() macro to be
simplified, in a later patch.

The output of existing files is not changed in any way, This commit just
adds new ones.

These changes may benefit from some reworking to send upstream, e.g. to
use a struct for the 'arg' parameter.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 scripts/kconfig/conf.c     |   6 +
 scripts/kconfig/confdata.c | 310 ++++++++++++++++++++++++++++++++++++-
 scripts/kconfig/expr.h     |  13 +-
 scripts/kconfig/lkc.h      |  10 +-
 4 files changed, 330 insertions(+), 9 deletions(-)

diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 376f796f674..40a3b8a45d0 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -684,6 +684,12 @@ int main(int ac, char **av)
 		break;
 	}
 
+	/* U-Boot: Mark symbols according to their SPL/non-SPL nature */
+	if (sync_kconfig) {
+		if (conf_mark_symbols())
+			exit(1);
+	}
+
 	if (sync_kconfig) {
 		/* syncconfig is used during the build so we shall update autoconf.
 		 * All other commands are only used to generate a config.
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 73bf43bcb95..cc1f133b0ea 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -16,6 +16,15 @@
 
 #include "lkc.h"
 
+/* Number of SPL prefixes we recognise */
+#define NUM_SPLS	 4
+
+/*
+ * SPL prefixes recognised. For example CONFIG_SPL_xxx is considered to be an
+ * SPL version of CONFIG_xxx
+ */
+static const char *spl_name[NUM_SPLS] = {"SPL", "TPL", "VPL", "TOOLS"};
+
 /* return true if 'path' exists, false otherwise */
 static bool is_present(const char *path)
 {
@@ -571,11 +580,88 @@ static struct conf_printer kconfig_printer_cb =
 	.print_comment = kconfig_print_comment,
 };
 
+/**
+ * get_spl_name() - Look up an SPL symbol
+ *
+ * This is used to get the name of a Kconfig option to write in an SPL context.
+ * If the symbol has an SPL symbol, this means it is used for U-Boot proper, so
+ * should not be written at all.
+ *
+ * Otherwise, this returns the name of the option. If the option is an SPL
+ * option, then the prefix (SPL_ or TPL_) is removed
+ *
+ * @sym: Symbol to look up
+ * @arg: Argument passed to the symbol function. This is void * but is actually
+ *	an int, indicating the SPL index / type (see spl_name[])
+ * @return name to write out for this symbol xxx:
+ *	NULL (don't write) if xxx has an associated SPL symbol
+ *	xxx if xxx is a non-SPL symbol
+ *	xxx if SPL_xxx is an SPL symbol
+ */
+static const char *get_spl_name(const struct symbol *sym, const void *arg)
+{
+	int spl = (long)arg;
+	const char *name = sym->name;
+
+	/*
+	 * Don't print it if this has an SPL symbol because processing of the
+	 * SPL symbol (e.g. SPL_FOO) will output CONFIG_FOO as well as
+	 * CONFIG_SPL_FOO
+	 */
+	if (sym->flags & SYMBOL_HAS_SPL)
+		return NULL;
+
+	/*
+	 * If it is SPL, only print it if the SPL_ prefix matches
+	 * Drop the prefix.
+	 */
+	if (sym->flags & SYMBOL_SPL) {
+		int len = strlen(spl_name[spl]);
+
+		if (!strncmp(name, spl_name[spl], len) && name[len] == '_')
+			name += len + 1;
+	}
+
+	return name;
+}
+
+/*
+ * auto.conf configuration printer for SPL
+ *
+ * This is used for creating auto.conf as well as SPL files like auto_spl.conf
+ *
+ * This printer is used when generating the resulting configuration after
+ * kconfig invocation and `defconfig' files. Unset symbol might be omitted by
+ * passing a non-NULL argument to the printer.
+ */
+static void spl_kconfig_print_symbol(FILE *fp, struct symbol *sym,
+				     const char *value, void *arg)
+{
+	const char *name;
+
+	name = get_spl_name(sym, arg);
+	if (!name)
+		return;
+
+	/*
+	 * If this is an SPL symbol, first print the symbol without the SPL
+	 * prefix
+	 */
+	if (name != sym->name)
+		print_makefile_sym(fp, name, sym->type, value, true);
+	if (!(sym->flags & SYMBOL_NO_SPL))
+		print_makefile_sym(fp, sym->name, sym->type, value, true);
+}
+
+static struct conf_printer spl_kconfig_printer_cb = {
+	.print_symbol = spl_kconfig_print_symbol,
+	.print_comment = kconfig_print_comment,
+};
+
 /* Print a symbol for a header file */
 static void print_header_sym(FILE *fp, const char *name, enum symbol_type type,
 			     const char *value)
 {
-
 	switch (type) {
 	case S_BOOLEAN:
 	case S_TRISTATE: {
@@ -651,6 +737,32 @@ static struct conf_printer header_printer_cb =
 	.print_comment = header_print_comment,
 };
 
+/*
+ * SPL header printer
+ *
+ * This printer is used when generating SPL files such as
+ * `include/generated/autoconf_spl.h'
+ */
+static void spl_header_print_symbol(FILE *fp, struct symbol *sym,
+				    const char *value, void *arg)
+{
+	const char *name;
+
+	name = get_spl_name(sym, arg);
+	if (!name)
+		return;
+
+	if (name != sym->name)
+		print_header_sym(fp, name, sym->type, value);
+	if (!(sym->flags & SYMBOL_NO_SPL))
+		print_header_sym(fp, sym->name, sym->type, value);
+}
+
+static struct conf_printer spl_header_printer_cb = {
+	.print_symbol = spl_header_print_symbol,
+	.print_comment = header_print_comment,
+};
+
 /*
  * Tristate printer
  *
@@ -1027,7 +1139,9 @@ int conf_write_autoconf(void)
 	struct symbol *sym;
 	const char *name;
 	FILE *out, *tristate, *out_h;
-	int i;
+	FILE *out_spl[NUM_SPLS];
+	FILE *out_h_spl[NUM_SPLS];
+	int i, spl;
 
 	sym_clear_all_valid();
 
@@ -1053,12 +1167,51 @@ int conf_write_autoconf(void)
 		return 1;
 	}
 
+	for (spl = 0; spl < NUM_SPLS; spl++) {
+		char fname[80];
+
+		snprintf(fname, sizeof(fname), ".tmpconfig_%s",
+			 spl_name[spl]);
+
+		out_spl[spl] = fopen(fname, "w");
+		if (!out_spl[spl]) {
+			while (spl--) {
+				fclose(out_spl[spl]);
+				fclose(out_h_spl[spl]);
+			}
+			fclose(out_h);
+			fclose(out);
+			fclose(tristate);
+			return 1;
+		}
+
+		snprintf(fname, sizeof(fname), ".tmpconfig_%s.h",
+			 spl_name[spl]);
+
+		out_h_spl[spl] = fopen(fname, "w");
+		if (!out_h_spl[spl]) {
+			fclose(out_spl[spl]);
+			while (spl--) {
+				fclose(out_spl[spl]);
+				fclose(out_h_spl[spl]);
+			}
+			fclose(out_h);
+			fclose(out);
+			fclose(tristate);
+			return 1;
+		}
+	}
+
 	conf_write_heading(out, &kconfig_printer_cb, NULL);
 
 	conf_write_heading(tristate, &tristate_printer_cb, NULL);
 
 	conf_write_heading(out_h, &header_printer_cb, NULL);
 
+	for (spl = 0; spl < NUM_SPLS; spl++)
+		conf_write_heading(out_h_spl[spl], &spl_header_printer_cb,
+				   (void *)(long)spl);
+
 	for_all_symbols(i, sym) {
 		sym_calc_value(sym);
 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
@@ -1070,10 +1223,24 @@ int conf_write_autoconf(void)
 		conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
 
 		conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
+
+		for (spl = 0; spl < NUM_SPLS; spl++) {
+			/* write make variables to auto_<spl>.conf */
+			conf_write_symbol(out_spl[spl], sym,
+					  &spl_kconfig_printer_cb,
+					  (void *)(long)spl);
+
+			/* write #defines to autoconf_<spl>.h */
+			conf_write_symbol(out_h_spl[spl], sym,
+					  &spl_header_printer_cb,
+					  (void *)(long)spl);
+		}
 	}
 	fclose(out);
 	fclose(tristate);
 	fclose(out_h);
+	for (spl = 0; spl < NUM_SPLS; spl++)
+		fclose(out_h_spl[spl]);
 
 	name = getenv("KCONFIG_AUTOHEADER");
 	if (!name)
@@ -1083,6 +1250,29 @@ int conf_write_autoconf(void)
 	if (rename(".tmpconfig.h", name))
 		return 1;
 
+	for (spl = 0; spl < NUM_SPLS; spl++) {
+		char tmpname[80], fname[80];
+		char *s;
+
+		snprintf(tmpname, sizeof(tmpname), ".tmpconfig_%s.h",
+			 spl_name[spl]);
+		snprintf(fname, sizeof(fname),
+			 "include/generated/autoconf_%s.h", spl_name[spl]);
+		for (s = fname; *s; s++)
+			*s = tolower(*s);
+		if (rename(tmpname, fname))
+			return 1;
+
+		snprintf(tmpname, sizeof(tmpname), ".tmpconfig_%s",
+			 spl_name[spl]);
+		snprintf(fname, sizeof(fname),
+			 "include/config/auto_%s.conf", spl_name[spl]);
+		for (s = fname; *s; s++)
+			*s = tolower(*s);
+		if (rename(tmpname, fname))
+			return 1;
+	}
+
 	name = getenv("KCONFIG_TRISTATE");
 	if (!name)
 		name = "include/config/tristate.conf";
@@ -1326,3 +1516,119 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
 
 	return has_changed;
 }
+
+static bool is_spl(const char *name, int *lenp)
+{
+	const char *uscore;
+	int len;
+	int i;
+
+	uscore = strchr(name, '_');
+	if (!uscore)
+		return false;
+
+	len = uscore - name;
+	for (i = 0; i < NUM_SPLS; i++) {
+		if (len == strlen(spl_name[i]) &&
+		    !strncmp(name, spl_name[i], len)) {
+			*lenp = len;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void conf_mark_spl_symbols(void)
+{
+	struct symbol *sym;
+	int i;
+
+	for_all_symbols(i, sym) if (sym->name) {
+		int len;
+		bool spl = is_spl(sym->name, &len);
+
+		if (spl) {
+			struct symbol *non_spl;
+
+			sym->flags |= SYMBOL_SPL;
+			non_spl = sym_find(sym->name + len + 1);
+			if (non_spl)
+				non_spl->flags |= SYMBOL_HAS_SPL;
+		}
+	}
+}
+
+static int process_file(const char *fname, bool search_spl)
+{
+	static char fullname[PATH_MAX+1];
+	const char *env;
+	char buf[256];
+	FILE *f;
+	char *s;
+
+	env = getenv(SRCTREE);
+	if (!env) {
+		fprintf(stderr, "No %s environment variable\n", SRCTREE);
+		return 1;
+	}
+	snprintf(fullname, sizeof(fullname), "%s/scripts/%s", env, fname);
+	f = fopen(fullname, "r");
+	if (!f) {
+		fprintf(stderr, "Cannot open '%s'\n", fullname);
+		return 1;
+	}
+	while (s = fgets(buf, sizeof(buf), f), s) {
+		struct symbol *sym;
+		int len;
+
+		len = strlen(s);
+		if (len)
+			s[len - 1] = '\0';
+		if (*s == '#' || !*s)
+			continue;
+
+		if (search_spl) {
+			int spl;
+
+			for (spl = 0; spl < NUM_SPLS; spl++) {
+				int slen;
+
+				slen = strlen(spl_name[spl]);
+				if (!strncmp(s, spl_name[spl], slen)) {
+					sym = sym_find(s + slen);
+					if (sym)
+						sym->flags |= SYMBOL_NO_PROPER;
+				}
+			}
+		} else {
+			sym = sym_find(s);
+			if (!sym) {
+				/*
+				 * perhaps we could drop these in config_nospl
+				 *
+				 * fprintf(stderr, "Unknown symbol from '%s': %s\n",
+				 *	fullname, s);
+				 */
+				continue;
+			}
+			sym->flags |= SYMBOL_NO_SPL;
+		}
+	}
+	fclose(f);
+
+	return 0;
+}
+
+int conf_mark_symbols(void)
+{
+	conf_mark_spl_symbols();
+	if (process_file("conf_nospl", false))
+		return 1;
+	if (process_file("conf_noproper", true))
+		return 1;
+
+	return 0;
+}
+
+//
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 656c87fb4f3..165685ff4e8 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -164,8 +164,17 @@ struct symbol {
 /* U-Boot: Marks a non-SPL symbol that also has an SPL version */
 #define SYMBOL_HAS_SPL		0x800000
 
-/* U-Boot: Marks an-SPL symbol that does not have a non-SPL version */
-#define SYMBOL_SPL_ONLY		0x1000000
+/*
+ * U-Boot: Marks a symbol with no SPL version. This is in the conf_nospl file
+ * and should not be enabled in any SPL build
+ */
+#define SYMBOL_NO_SPL		0x1000000
+
+/*
+ * U-Boot: Marks an SPL symbol that does not have a non-SPL version. This is in
+ * conf_noproper so should not be enabled in U-Boot proper
+  */
+#define SYMBOL_NO_PROPER	0x2000000
 
 #define SYMBOL_MAXLENGTH	256
 #define SYMBOL_HASHSIZE		9973
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index dec03cc927a..592610483f0 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -72,13 +72,13 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode);
 void set_all_choice_values(struct symbol *csym);
 
 /**
- * conf_mark_spl_symbols() - Mark SPL symbols
+ * conf_mark_symbols() - Mark symbols with U-Boot flags
  *
- * Symbols which don't start with SPL_ (TPL_, etc.) but have an SPL version
- * should be marked with the SYMBOL_SPL flag, so we know to avoid writing them
- * in the SPL autoconf.h files.
+ * Symbols which don't have an SPL symbol are marked with SYMBOL_PROPER_ONLY and
+ * those with only SPL symbols are marked withSYMBOL_SPL_ONLY, so we know to
+ * avoid writing them to the wrong autoconf.h files.
  */
-void conf_mark_spl_symbols(void);
+int conf_mark_symbols(void);
 
 /* confdata.c and expr.c */
 static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
-- 
2.39.1.456.gfc5497dd1b-goog



More information about the U-Boot mailing list