summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-23 23:32:21 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-23 23:32:21 +0200
commitca83c61cb3db964061ea186654bf8e1879589de3 (patch)
tree03800737bef31697d19aeca41f87284777e46b5e /scripts
parentMerge tag 'rpmsg-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/remo... (diff)
parentkbuild: doc: gcc to CC change (diff)
downloadlinux-ca83c61cb3db964061ea186654bf8e1879589de3.tar.xz
linux-ca83c61cb3db964061ea186654bf8e1879589de3.zip
Merge tag 'kbuild-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild
Pull Kbuild updates from Masahiro Yamada: - Remove tristate choice support from Kconfig - Stop using the PROVIDE() directive in the linker script - Reduce the number of links for the combination of CONFIG_KALLSYMS and CONFIG_DEBUG_INFO_BTF - Enable the warning for symbol reference to .exit.* sections by default - Fix warnings in RPM package builds - Improve scripts/make_fit.py to generate a FIT image with separate base DTB and overlays - Improve choice value calculation in Kconfig - Fix conditional prompt behavior in choice in Kconfig - Remove support for the uncommon EMAIL environment variable in Debian package builds - Remove support for the uncommon "name <email>" form for the DEBEMAIL environment variable - Raise the minimum supported GNU Make version to 4.0 - Remove stale code for the absolute kallsyms - Move header files commonly used for host programs to scripts/include/ - Introduce the pacman-pkg target to generate a pacman package used in Arch Linux - Clean up Kconfig * tag 'kbuild-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (65 commits) kbuild: doc: gcc to CC change kallsyms: change sym_entry::percpu_absolute to bool type kallsyms: unify seq and start_pos fields of struct sym_entry kallsyms: add more original symbol type/name in comment lines kallsyms: use \t instead of a tab in printf() kallsyms: avoid repeated calculation of array size for markers kbuild: add script and target to generate pacman package modpost: use generic macros for hash table implementation kbuild: move some helper headers from scripts/kconfig/ to scripts/include/ Makefile: add comment to discourage tools/* addition for kernel builds kbuild: clean up scripts/remove-stale-files kconfig: recursive checks drop file/lineno kbuild: rpm-pkg: introduce a simple changelog section for kernel.spec kallsyms: get rid of code for absolute kallsyms kbuild: Create INSTALL_PATH directory if it does not exist kbuild: Abort make on install failures kconfig: remove 'e1' and 'e2' macros from expression deduplication kconfig: remove SYMBOL_CHOICEVAL flag kconfig: add const qualifiers to several function arguments kconfig: call expr_eliminate_yn() at least once in expr_eliminate_dups() ...
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Kbuild.include2
-rw-r--r--scripts/Makefile.lib9
-rw-r--r--scripts/Makefile.package14
-rwxr-xr-xscripts/build-version10
-rw-r--r--scripts/include/array_size.h (renamed from scripts/kconfig/array_size.h)0
-rw-r--r--scripts/include/hashtable.h (renamed from scripts/kconfig/hashtable.h)0
-rw-r--r--scripts/include/list.h (renamed from scripts/kconfig/list.h)53
-rw-r--r--scripts/include/list_types.h (renamed from scripts/kconfig/list_types.h)0
-rwxr-xr-xscripts/install.sh4
-rw-r--r--scripts/kallsyms.c123
-rw-r--r--scripts/kconfig/conf.c230
-rw-r--r--scripts/kconfig/confdata.c129
-rw-r--r--scripts/kconfig/expr.c128
-rw-r--r--scripts/kconfig/expr.h29
-rwxr-xr-xscripts/kconfig/gconf-cfg.sh2
-rw-r--r--scripts/kconfig/gconf.c26
-rw-r--r--scripts/kconfig/internal.h2
-rw-r--r--scripts/kconfig/lkc.h34
-rw-r--r--scripts/kconfig/lkc_proto.h16
-rwxr-xr-xscripts/kconfig/mconf-cfg.sh2
-rw-r--r--scripts/kconfig/mconf.c38
-rw-r--r--scripts/kconfig/menu.c111
-rw-r--r--scripts/kconfig/mnconf-common.c2
-rw-r--r--scripts/kconfig/mnconf-common.h2
-rwxr-xr-xscripts/kconfig/nconf-cfg.sh2
-rw-r--r--scripts/kconfig/nconf.c38
-rw-r--r--scripts/kconfig/parser.y45
-rw-r--r--scripts/kconfig/preprocess.c4
-rwxr-xr-xscripts/kconfig/qconf-cfg.sh2
-rw-r--r--scripts/kconfig/qconf.cc20
-rw-r--r--scripts/kconfig/qconf.h2
-rw-r--r--scripts/kconfig/symbol.c373
-rw-r--r--scripts/kconfig/tests/choice/Kconfig17
-rw-r--r--scripts/kconfig/tests/choice/__init__.py10
-rw-r--r--scripts/kconfig/tests/choice/alldef_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/allmod_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/allno_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/allyes_expected_config3
-rw-r--r--scripts/kconfig/tests/choice/oldask0_expected_stdout4
-rw-r--r--scripts/kconfig/tests/choice/oldask1_config1
-rw-r--r--scripts/kconfig/tests/choice/oldask1_expected_stdout9
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/Kconfig21
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/__init__.py16
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/config2
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/expected_config3
-rw-r--r--scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout4
-rw-r--r--scripts/kconfig/tests/err_recursive_dep/expected_stderr36
-rw-r--r--scripts/kconfig/tests/inter_choice/Kconfig25
-rw-r--r--scripts/kconfig/tests/inter_choice/__init__.py15
-rw-r--r--scripts/kconfig/tests/inter_choice/defconfig1
-rw-r--r--scripts/kconfig/tests/inter_choice/expected_config4
-rw-r--r--scripts/kconfig/util.c4
-rwxr-xr-xscripts/link-vmlinux.sh105
-rwxr-xr-xscripts/make_fit.py86
-rw-r--r--scripts/mod/list.h213
-rw-r--r--scripts/mod/modpost.c67
-rw-r--r--scripts/mod/modpost.h2
-rw-r--r--scripts/package/PKGBUILD108
-rwxr-xr-xscripts/package/builddeb2
-rwxr-xr-xscripts/package/buildtar2
-rwxr-xr-xscripts/package/gen-diff-patch2
-rwxr-xr-xscripts/package/install-extmod-build5
-rw-r--r--scripts/package/kernel.spec2
-rwxr-xr-xscripts/package/mkdebian44
-rwxr-xr-xscripts/package/mkspec27
-rwxr-xr-xscripts/remove-stale-files18
66 files changed, 952 insertions, 1367 deletions
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index faf37bafa3f8..ed8a7493524b 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -68,7 +68,7 @@ kbuild-file = $(or $(wildcard $(src)/Kbuild),$(src)/Makefile)
# Read a file, replacing newlines with spaces
#
# Make 4.2 or later can read a file by using its builtin function.
-ifneq ($(filter-out 3.% 4.0 4.1, $(MAKE_VERSION)),)
+ifneq ($(filter-out 4.0 4.1, $(MAKE_VERSION)),)
read-file = $(subst $(newline),$(space),$(file < $1))
else
read-file = $(shell cat $1 2>/dev/null)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 29da0dc9776d..fe3668dc4954 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -409,12 +409,16 @@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ;
DT_CHECK_CMD = $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA)
+# NOTE:
+# Do not replace $(filter %.dtb %.dtbo, $^) with $(real-prereqs). When a single
+# DTB is turned into a multi-blob DTB, $^ will contain header file dependencies
+# recorded in the .*.cmd file.
ifneq ($(CHECK_DTBS),)
quiet_cmd_fdtoverlay = DTOVLCH $@
- cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(real-prereqs) ; $(DT_CHECK_CMD) $@ || true
+ cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(filter %.dtb %.dtbo, $^) ; $(DT_CHECK_CMD) $@ || true
else
quiet_cmd_fdtoverlay = DTOVL $@
- cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(real-prereqs)
+ cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(filter %.dtb %.dtbo, $^)
endif
$(multi-dtb-y): FORCE
@@ -529,6 +533,7 @@ quiet_cmd_fit = FIT $@
cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
--name '$(UIMAGE_NAME)' \
$(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
+ $(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
--compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
# XZ
diff --git a/scripts/Makefile.package b/scripts/Makefile.package
index bf016af8bf8a..4a80584ec771 100644
--- a/scripts/Makefile.package
+++ b/scripts/Makefile.package
@@ -141,6 +141,19 @@ snap-pkg:
cd $(objtree)/snap && \
snapcraft --target-arch=$(UTS_MACHINE)
+# pacman-pkg
+# ---------------------------------------------------------------------------
+
+PHONY += pacman-pkg
+pacman-pkg:
+ @ln -srf $(srctree)/scripts/package/PKGBUILD $(objtree)/PKGBUILD
+ +objtree="$(realpath $(objtree))" \
+ BUILDDIR="$(realpath $(objtree))/pacman" \
+ CARCH="$(UTS_MACHINE)" \
+ KBUILD_MAKEFLAGS="$(MAKEFLAGS)" \
+ KBUILD_REVISION="$(shell $(srctree)/scripts/build-version)" \
+ makepkg $(MAKEPKGOPTS)
+
# dir-pkg tar*-pkg - tarball targets
# ---------------------------------------------------------------------------
@@ -221,6 +234,7 @@ help:
@echo ' bindeb-pkg - Build only the binary kernel deb package'
@echo ' snap-pkg - Build only the binary kernel snap package'
@echo ' (will connect to external hosts)'
+ @echo ' pacman-pkg - Build only the binary kernel pacman package'
@echo ' dir-pkg - Build the kernel as a plain directory structure'
@echo ' tar-pkg - Build the kernel as an uncompressed tarball'
@echo ' targz-pkg - Build the kernel as a gzip compressed tarball'
diff --git a/scripts/build-version b/scripts/build-version
new file mode 100755
index 000000000000..537d45815083
--- /dev/null
+++ b/scripts/build-version
@@ -0,0 +1,10 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+
+prev_ver=$(cat .version 2>/dev/null) &&
+ver=$(expr ${prev_ver} + 1 2>/dev/null) ||
+ver=1
+
+echo ${ver} > .version
+
+echo ${ver}
diff --git a/scripts/kconfig/array_size.h b/scripts/include/array_size.h
index 26ba78d867d1..26ba78d867d1 100644
--- a/scripts/kconfig/array_size.h
+++ b/scripts/include/array_size.h
diff --git a/scripts/kconfig/hashtable.h b/scripts/include/hashtable.h
index a0a2c8f5f639..a0a2c8f5f639 100644
--- a/scripts/kconfig/hashtable.h
+++ b/scripts/include/hashtable.h
diff --git a/scripts/kconfig/list.h b/scripts/include/list.h
index 882859ddf9f4..409201cd495b 100644
--- a/scripts/kconfig/list.h
+++ b/scripts/include/list.h
@@ -128,6 +128,29 @@ static inline void list_del(struct list_head *entry)
}
/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add_tail(list, head);
+}
+
+/**
* list_is_head - tests whether @list is the list @head
* @list: the entry to test
* @head: the head of the list
@@ -167,6 +190,17 @@ static inline int list_empty(const struct list_head *head)
list_entry((ptr)->next, type, member)
/**
+ * list_last_entry - get the last element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
@@ -175,6 +209,14 @@ static inline int list_empty(const struct list_head *head)
list_entry((pos)->member.next, typeof(*(pos)), member)
/**
+ * list_prev_entry - get the prev element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_prev_entry(pos, member) \
+ list_entry((pos)->member.prev, typeof(*(pos)), member)
+
+/**
* list_entry_is_head - test if the entry points to the head of the list
* @pos: the type * to cursor
* @head: the head for your list.
@@ -195,6 +237,17 @@ static inline int list_empty(const struct list_head *head)
pos = list_next_entry(pos, member))
/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_last_entry(head, typeof(*pos), member); \
+ !list_entry_is_head(pos, head, member); \
+ pos = list_prev_entry(pos, member))
+
+/**
* list_for_each_entry_safe - iterate over list of given type. Safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
diff --git a/scripts/kconfig/list_types.h b/scripts/include/list_types.h
index d935b7c5aa81..d935b7c5aa81 100644
--- a/scripts/kconfig/list_types.h
+++ b/scripts/include/list_types.h
diff --git a/scripts/install.sh b/scripts/install.sh
index 9bb0fb44f04a..05d62ac513ee 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -20,6 +20,10 @@ do
fi
done
+if [ -n "${INSTALL_PATH}" ] && ! [ -e "${INSTALL_PATH}" ]; then
+ mkdir -p "${INSTALL_PATH}"
+fi
+
# User/arch may have a custom install script
for file in "${HOME}/bin/${INSTALLKERNEL}" \
"/sbin/${INSTALLKERNEL}" \
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 47978efe4797..0ed873491bf5 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -6,7 +6,7 @@
* of the GNU General Public License, incorporated herein by reference.
*
* Usage: kallsyms [--all-symbols] [--absolute-percpu]
- * [--base-relative] [--lto-clang] in.map > out.S
+ * [--lto-clang] in.map > out.S
*
* Table compression uses all the unused char codes on the symbols and
* maps these to the most used substrings (tokens). For instance, it might
@@ -36,8 +36,7 @@ struct sym_entry {
unsigned long long addr;
unsigned int len;
unsigned int seq;
- unsigned int start_pos;
- unsigned int percpu_absolute;
+ bool percpu_absolute;
unsigned char sym[];
};
@@ -63,7 +62,6 @@ static struct sym_entry **table;
static unsigned int table_size, table_cnt;
static int all_symbols;
static int absolute_percpu;
-static int base_relative;
static int lto_clang;
static int token_profit[0x10000];
@@ -76,7 +74,7 @@ static unsigned char best_table_len[256];
static void usage(void)
{
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] "
- "[--base-relative] [--lto-clang] in.map > out.S\n");
+ "[--lto-clang] in.map > out.S\n");
exit(1);
}
@@ -183,7 +181,7 @@ static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len)
sym->len = len;
sym->sym[0] = type;
strcpy(sym_name(sym), name);
- sym->percpu_absolute = 0;
+ sym->percpu_absolute = false;
return sym;
}
@@ -259,12 +257,6 @@ static void shrink_table(void)
}
}
table_cnt = pos;
-
- /* When valid symbol is not registered, exit to error */
- if (!table_cnt) {
- fprintf(stderr, "No valid symbol.\n");
- exit(1);
- }
}
static void read_map(const char *in)
@@ -285,7 +277,7 @@ static void read_map(const char *in)
if (!sym)
continue;
- sym->start_pos = table_cnt;
+ sym->seq = table_cnt;
if (table_cnt >= table_size) {
table_size += 10000;
@@ -347,7 +339,7 @@ static int expand_symbol(const unsigned char *data, int len, char *result)
return total;
}
-static int symbol_absolute(const struct sym_entry *s)
+static bool symbol_absolute(const struct sym_entry *s)
{
return s->percpu_absolute;
}
@@ -400,7 +392,7 @@ static void write_src(void)
{
unsigned int i, k, off;
unsigned int best_idx[256];
- unsigned int *markers;
+ unsigned int *markers, markers_cnt;
char buf[KSYM_NAME_LEN];
printf("#include <asm/bitsperlong.h>\n");
@@ -420,7 +412,8 @@ static void write_src(void)
/* table of offset markers, that give the offset in the compressed stream
* every 256 symbols */
- markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
+ markers_cnt = (table_cnt + 255) / 256;
+ markers = malloc(sizeof(*markers) * markers_cnt);
if (!markers) {
fprintf(stderr, "kallsyms failure: "
"unable to allocate required memory\n");
@@ -462,21 +455,19 @@ static void write_src(void)
}
for (k = 0; k < table[i]->len; k++)
printf(", 0x%02x", table[i]->sym[k]);
- printf("\n");
- }
- printf("\n");
- /*
- * Now that we wrote out the compressed symbol names, restore the
- * original names, which are needed in some of the later steps.
- */
- for (i = 0; i < table_cnt; i++) {
+ /*
+ * Now that we wrote out the compressed symbol name, restore the
+ * original name and print it in the comment.
+ */
expand_symbol(table[i]->sym, table[i]->len, buf);
strcpy((char *)table[i]->sym, buf);
+ printf("\t/* %s */\n", table[i]->sym);
}
+ printf("\n");
output_label("kallsyms_markers");
- for (i = 0; i < ((table_cnt + 255) >> 8); i++)
+ for (i = 0; i < markers_cnt; i++)
printf("\t.long\t%u\n", markers[i]);
printf("\n");
@@ -497,54 +488,43 @@ static void write_src(void)
printf("\t.short\t%d\n", best_idx[i]);
printf("\n");
- if (!base_relative)
- output_label("kallsyms_addresses");
- else
- output_label("kallsyms_offsets");
+ output_label("kallsyms_offsets");
for (i = 0; i < table_cnt; i++) {
- if (base_relative) {
- /*
- * Use the offset relative to the lowest value
- * encountered of all relative symbols, and emit
- * non-relocatable fixed offsets that will be fixed
- * up at runtime.
- */
+ /*
+ * Use the offset relative to the lowest value
+ * encountered of all relative symbols, and emit
+ * non-relocatable fixed offsets that will be fixed
+ * up at runtime.
+ */
- long long offset;
- int overflow;
-
- if (!absolute_percpu) {
- offset = table[i]->addr - relative_base;
- overflow = (offset < 0 || offset > UINT_MAX);
- } else if (symbol_absolute(table[i])) {
- offset = table[i]->addr;
- overflow = (offset < 0 || offset > INT_MAX);
- } else {
- offset = relative_base - table[i]->addr - 1;
- overflow = (offset < INT_MIN || offset >= 0);
- }
- if (overflow) {
- fprintf(stderr, "kallsyms failure: "
- "%s symbol value %#llx out of range in relative mode\n",
- symbol_absolute(table[i]) ? "absolute" : "relative",
- table[i]->addr);
- exit(EXIT_FAILURE);
- }
- printf("\t.long\t%#x /* %s */\n", (int)offset, table[i]->sym);
- } else if (!symbol_absolute(table[i])) {
- output_address(table[i]->addr);
+ long long offset;
+ int overflow;
+
+ if (!absolute_percpu) {
+ offset = table[i]->addr - relative_base;
+ overflow = (offset < 0 || offset > UINT_MAX);
+ } else if (symbol_absolute(table[i])) {
+ offset = table[i]->addr;
+ overflow = (offset < 0 || offset > INT_MAX);
} else {
- printf("\tPTR\t%#llx\n", table[i]->addr);
+ offset = relative_base - table[i]->addr - 1;
+ overflow = (offset < INT_MIN || offset >= 0);
+ }
+ if (overflow) {
+ fprintf(stderr, "kallsyms failure: "
+ "%s symbol value %#llx out of range in relative mode\n",
+ symbol_absolute(table[i]) ? "absolute" : "relative",
+ table[i]->addr);
+ exit(EXIT_FAILURE);
}
+ printf("\t.long\t%#x\t/* %s */\n", (int)offset, table[i]->sym);
}
printf("\n");
- if (base_relative) {
- output_label("kallsyms_relative_base");
- output_address(relative_base);
- printf("\n");
- }
+ output_label("kallsyms_relative_base");
+ output_address(relative_base);
+ printf("\n");
if (lto_clang)
for (i = 0; i < table_cnt; i++)
@@ -553,10 +533,11 @@ static void write_src(void)
sort_symbols_by_name();
output_label("kallsyms_seqs_of_names");
for (i = 0; i < table_cnt; i++)
- printf("\t.byte 0x%02x, 0x%02x, 0x%02x\n",
+ printf("\t.byte 0x%02x, 0x%02x, 0x%02x\t/* %s */\n",
(unsigned char)(table[i]->seq >> 16),
(unsigned char)(table[i]->seq >> 8),
- (unsigned char)(table[i]->seq >> 0));
+ (unsigned char)(table[i]->seq >> 0),
+ table[i]->sym);
printf("\n");
}
@@ -780,7 +761,7 @@ static int compare_symbols(const void *a, const void *b)
return wa - wb;
/* sort by initial order, so that other symbols are left undisturbed */
- return sa->start_pos - sb->start_pos;
+ return sa->seq - sb->seq;
}
static void sort_symbols(void)
@@ -800,7 +781,7 @@ static void make_percpus_absolute(void)
* versions of this tool.
*/
table[i]->sym[0] = 'A';
- table[i]->percpu_absolute = 1;
+ table[i]->percpu_absolute = true;
}
}
@@ -826,7 +807,6 @@ int main(int argc, char **argv)
static const struct option long_options[] = {
{"all-symbols", no_argument, &all_symbols, 1},
{"absolute-percpu", no_argument, &absolute_percpu, 1},
- {"base-relative", no_argument, &base_relative, 1},
{"lto-clang", no_argument, &lto_clang, 1},
{},
};
@@ -847,8 +827,7 @@ int main(int argc, char **argv)
if (absolute_percpu)
make_percpus_absolute();
sort_symbols();
- if (base_relative)
- record_relative_base();
+ record_relative_base();
optimize_token_table();
write_src();
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 8ad2c52d9b1f..3d7d454c54da 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -114,51 +114,54 @@ static void set_randconfig_seed(void)
srand(seed);
}
-static bool randomize_choice_values(struct symbol *csym)
+/**
+ * randomize_choice_values - randomize choice block
+ *
+ * @choice: menu entry for the choice
+ */
+static void randomize_choice_values(struct menu *choice)
{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
- int cnt, def;
+ struct menu *menu;
+ int x;
+ int cnt = 0;
/*
- * If choice is mod then we may have more items selected
- * and if no then no-one.
- * In both cases stop.
+ * First, count the number of symbols to randomize. If sym_has_value()
+ * is true, it was specified by KCONFIG_ALLCONFIG. It needs to be
+ * respected.
*/
- if (csym->curr.tri != yes)
- return false;
+ menu_for_each_sub_entry(menu, choice) {
+ struct symbol *sym = menu->sym;
- prop = sym_get_choice_prop(csym);
+ if (sym && !sym_has_value(sym))
+ cnt++;
+ }
- /* count entries in choice block */
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym)
- cnt++;
+ while (cnt > 0) {
+ x = rand() % cnt;
- /*
- * find a random value and set it to yes,
- * set the rest to no so we have only one set
- */
- def = rand() % cnt;
-
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (def == cnt++) {
- sym->def[S_DEF_USER].tri = yes;
- csym->def[S_DEF_USER].val = sym;
- } else {
- sym->def[S_DEF_USER].tri = no;
+ menu_for_each_sub_entry(menu, choice) {
+ struct symbol *sym = menu->sym;
+
+ if (sym && !sym_has_value(sym))
+ x--;
+
+ if (x < 0) {
+ sym->def[S_DEF_USER].tri = yes;
+ sym->flags |= SYMBOL_DEF_USER;
+ /*
+ * Move the selected item to the _tail_ because
+ * this needs to have a lower priority than the
+ * user input from KCONFIG_ALLCONFIG.
+ */
+ list_move_tail(&sym->choice_link,
+ &choice->choice_members);
+
+ break;
+ }
}
- sym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- sym->flags &= ~SYMBOL_VALID;
+ cnt--;
}
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~SYMBOL_VALID;
-
- return true;
}
enum conf_def_mode {
@@ -169,9 +172,9 @@ enum conf_def_mode {
def_random
};
-static bool conf_set_all_new_symbols(enum conf_def_mode mode)
+static void conf_set_all_new_symbols(enum conf_def_mode mode)
{
- struct symbol *sym, *csym;
+ struct menu *menu;
int cnt;
/*
* can't go as the default in switch-case below, otherwise gcc whines
@@ -180,7 +183,6 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
int pby = 50; /* probability of bool = y */
int pty = 33; /* probability of tristate = y */
int ptm = 33; /* probability of tristate = m */
- bool has_changed = false;
if (mode == def_random) {
int n, p[3];
@@ -227,79 +229,51 @@ static bool conf_set_all_new_symbols(enum conf_def_mode mode)
}
}
- for_all_symbols(sym) {
- if (sym_has_value(sym) || sym->flags & SYMBOL_VALID)
- continue;
- switch (sym_get_type(sym)) {
- case S_BOOLEAN:
- case S_TRISTATE:
- has_changed = true;
- switch (mode) {
- case def_yes:
- sym->def[S_DEF_USER].tri = yes;
- break;
- case def_mod:
- sym->def[S_DEF_USER].tri = mod;
- break;
- case def_no:
- sym->def[S_DEF_USER].tri = no;
- break;
- case def_random:
- sym->def[S_DEF_USER].tri = no;
- cnt = rand() % 100;
- if (sym->type == S_TRISTATE) {
- if (cnt < pty)
- sym->def[S_DEF_USER].tri = yes;
- else if (cnt < pty + ptm)
- sym->def[S_DEF_USER].tri = mod;
- } else if (cnt < pby)
- sym->def[S_DEF_USER].tri = yes;
- break;
- default:
- continue;
- }
- if (!(sym_is_choice(sym) && mode == def_random))
- sym->flags |= SYMBOL_DEF_USER;
- break;
- default:
- break;
- }
-
- }
+ menu_for_each_entry(menu) {
+ struct symbol *sym = menu->sym;
+ tristate val;
- sym_clear_all_valid();
+ if (!sym || !menu->prompt || sym_has_value(sym) ||
+ (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
+ sym_is_choice_value(sym))
+ continue;
- /*
- * We have different type of choice blocks.
- * If curr.tri equals to mod then we can select several
- * choice symbols in one block.
- * In this case we do nothing.
- * If curr.tri equals yes then only one symbol can be
- * selected in a choice block and we set it to yes,
- * and the rest to no.
- */
- if (mode != def_random) {
- for_all_symbols(csym) {
- if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
- sym_is_choice_value(csym))
- csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
+ if (sym_is_choice(sym)) {
+ if (mode == def_random)
+ randomize_choice_values(menu);
+ continue;
}
- }
- for_all_symbols(csym) {
- if (sym_has_value(csym) || !sym_is_choice(csym))
+ switch (mode) {
+ case def_yes:
+ val = yes;
+ break;
+ case def_mod:
+ val = mod;
+ break;
+ case def_no:
+ val = no;
+ break;
+ case def_random:
+ val = no;
+ cnt = rand() % 100;
+ if (sym->type == S_TRISTATE) {
+ if (cnt < pty)
+ val = yes;
+ else if (cnt < pty + ptm)
+ val = mod;
+ } else if (cnt < pby) {
+ val = yes;
+ }
+ break;
+ default:
continue;
-
- sym_calc_value(csym);
- if (mode == def_random)
- has_changed |= randomize_choice_values(csym);
- else {
- set_all_choice_values(csym);
- has_changed = true;
}
+ sym->def[S_DEF_USER].tri = val;
+ sym->flags |= SYMBOL_DEF_USER;
}
- return has_changed;
+ sym_clear_all_valid();
}
static void conf_rewrite_tristates(tristate old_val, tristate new_val)
@@ -448,39 +422,15 @@ help:
static void conf_choice(struct menu *menu)
{
- struct symbol *sym, *def_sym;
+ struct symbol *def_sym;
struct menu *child;
- bool is_new;
-
- sym = menu->sym;
- is_new = !sym_has_value(sym);
- if (sym_is_changeable(sym)) {
- conf_sym(menu);
- sym_calc_value(sym);
- switch (sym_get_tristate_value(sym)) {
- case no:
- case mod:
- return;
- case yes:
- break;
- }
- } else {
- switch (sym_get_tristate_value(sym)) {
- case no:
- return;
- case mod:
- printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
- return;
- case yes:
- break;
- }
- }
+ bool is_new = false;
while (1) {
int cnt, def;
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
- def_sym = sym_get_choice_value(sym);
+ def_sym = sym_calc_choice(menu);
cnt = def = 0;
line[0] = 0;
for (child = menu->list; child; child = child->next) {
@@ -498,8 +448,10 @@ static void conf_choice(struct menu *menu)
printf("%*c", indent, ' ');
printf(" %d. %s (%s)", cnt, menu_get_prompt(child),
child->sym->name);
- if (!sym_has_value(child->sym))
+ if (!sym_has_value(child->sym)) {
+ is_new = true;
printf(" (NEW)");
+ }
printf("\n");
}
printf("%*schoice", indent - 1, "");
@@ -549,7 +501,7 @@ static void conf_choice(struct menu *menu)
print_help(child);
continue;
}
- sym_set_tristate_value(child->sym, yes);
+ choice_set_value(menu, child->sym);
return;
}
}
@@ -596,9 +548,7 @@ static void conf(struct menu *menu)
if (sym_is_choice(sym)) {
conf_choice(menu);
- if (sym->curr.tri != mod)
- return;
- goto conf_childs;
+ return;
}
switch (sym->type) {
@@ -630,10 +580,7 @@ static void check_conf(struct menu *menu)
return;
sym = menu->sym;
- if (sym && !sym_has_value(sym) &&
- (sym_is_changeable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) {
-
+ if (sym && !sym_has_value(sym) && sym_is_changeable(sym)) {
switch (input_mode) {
case listnewconfig:
if (sym->name)
@@ -849,8 +796,7 @@ int main(int ac, char **av)
conf_set_all_new_symbols(def_default);
break;
case randconfig:
- /* Really nothing to do in this loop */
- while (conf_set_all_new_symbols(def_random)) ;
+ conf_set_all_new_symbols(def_random);
break;
case defconfig:
conf_set_all_new_symbols(def_default);
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 85b53069ba7a..76193ce5a792 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -382,10 +382,7 @@ load:
def_flags = SYMBOL_DEF << def;
for_all_symbols(sym) {
- sym->flags |= SYMBOL_CHANGED;
sym->flags &= ~(def_flags|SYMBOL_VALID);
- if (sym_is_choice(sym))
- sym->flags |= def_flags;
switch (sym->type) {
case S_INT:
case S_HEX:
@@ -399,6 +396,8 @@ load:
}
while (getline_stripped(&line, &line_asize, in) != -1) {
+ struct menu *choice;
+
conf_lineno++;
if (!line[0]) /* blank line */
@@ -460,25 +459,14 @@ load:
if (conf_set_sym_val(sym, def, def_flags, val))
continue;
- if (sym && sym_is_choice_value(sym)) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- switch (sym->def[def].tri) {
- case no:
- break;
- case mod:
- if (cs->def[def].tri == yes) {
- conf_warning("%s creates inconsistent choice state", sym->name);
- cs->flags &= ~def_flags;
- }
- break;
- case yes:
- if (cs->def[def].tri != no)
- conf_warning("override: %s changes choice state", sym->name);
- cs->def[def].val = sym;
- break;
- }
- cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
- }
+ /*
+ * If this is a choice member, give it the highest priority.
+ * If conflicting CONFIG options are given from an input file,
+ * the last one wins.
+ */
+ choice = sym_get_choice_menu(sym);
+ if (choice)
+ list_move(&sym->choice_link, &choice->choice_members);
}
free(line);
fclose(in);
@@ -489,7 +477,6 @@ load:
int conf_read(const char *name)
{
struct symbol *sym;
- int conf_unsaved = 0;
conf_set_changed(false);
@@ -520,23 +507,11 @@ int conf_read(const char *name)
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
/* no previous value and not saved */
continue;
- conf_unsaved++;
+ conf_set_changed(true);
/* maybe print value in verbose mode... */
}
- for_all_symbols(sym) {
- if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
- /* Reset values of generates values, so they'll appear
- * as new, if they should become visible, but that
- * doesn't quite work if the Kconfig and the saved
- * configuration disagree.
- */
- if (sym->visible == no && !conf_unsaved)
- sym->flags &= ~SYMBOL_DEF_USER;
- }
- }
-
- if (conf_warnings || conf_unsaved)
+ if (conf_warnings)
conf_set_changed(true);
return 0;
@@ -784,35 +759,31 @@ int conf_write_defconfig(const char *filename)
struct menu *choice;
sym = menu->sym;
- if (sym && !sym_is_choice(sym)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- continue;
- sym->flags &= ~SYMBOL_WRITE;
- /* If we cannot change the symbol - skip */
- if (!sym_is_changeable(sym))
- continue;
- /* If symbol equals to default value - skip */
- if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
- continue;
- /*
- * If symbol is a choice value and equals to the
- * default for a choice - skip.
- */
- choice = sym_get_choice_menu(sym);
- if (choice) {
- struct symbol *ds;
-
- ds = sym_choice_default(choice->sym);
- if (sym == ds) {
- if ((sym->type == S_BOOLEAN) &&
- sym_get_tristate_value(sym) == yes)
- continue;
- }
- }
- print_symbol_for_dotconfig(out, sym);
+ if (!sym || sym_is_choice(sym))
+ continue;
+
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ continue;
+ sym->flags &= ~SYMBOL_WRITE;
+ /* Skip unchangeable symbols */
+ if (!sym_is_changeable(sym))
+ continue;
+ /* Skip symbols that are equal to the default */
+ if (!strcmp(sym_get_string_value(sym), sym_get_string_default(sym)))
+ continue;
+
+ /* Skip choice values that are equal to the default */
+ choice = sym_get_choice_menu(sym);
+ if (choice) {
+ struct symbol *ds;
+
+ ds = sym_choice_default(choice);
+ if (sym == ds && sym_get_tristate_value(sym) == yes)
+ continue;
}
+ print_symbol_for_dotconfig(out, sym);
}
fclose(out);
return 0;
@@ -1141,16 +1112,14 @@ int conf_write_autoconf(int overwrite)
}
static bool conf_changed;
-static void (*conf_changed_callback)(void);
+static void (*conf_changed_callback)(bool);
void conf_set_changed(bool val)
{
- bool changed = conf_changed != val;
+ if (conf_changed_callback && conf_changed != val)
+ conf_changed_callback(val);
conf_changed = val;
-
- if (conf_changed_callback && changed)
- conf_changed_callback();
}
bool conf_get_changed(void)
@@ -1158,27 +1127,7 @@ bool conf_get_changed(void)
return conf_changed;
}
-void conf_set_changed_callback(void (*fn)(void))
+void conf_set_changed_callback(void (*fn)(bool))
{
conf_changed_callback = fn;
}
-
-void set_all_choice_values(struct symbol *csym)
-{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
-
- prop = sym_get_choice_prop(csym);
-
- /*
- * Set all non-assinged choice values to no
- */
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (!sym_has_value(sym))
- sym->def[S_DEF_USER].tri = no;
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
-}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index fcc190b67b6f..c349da7fe3f8 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -90,7 +90,6 @@ struct expr *expr_copy(const struct expr *org)
break;
case E_AND:
case E_OR:
- case E_LIST:
e->left.expr = expr_copy(org->left.expr);
e->right.expr = expr_copy(org->right.expr);
break;
@@ -136,9 +135,6 @@ void expr_free(struct expr *e)
static int trans_count;
-#define e1 (*ep1)
-#define e2 (*ep2)
-
/*
* expr_eliminate_eq() helper.
*
@@ -151,38 +147,38 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
{
/* Recurse down to leaves */
- if (e1->type == type) {
- __expr_eliminate_eq(type, &e1->left.expr, &e2);
- __expr_eliminate_eq(type, &e1->right.expr, &e2);
+ if ((*ep1)->type == type) {
+ __expr_eliminate_eq(type, &(*ep1)->left.expr, ep2);
+ __expr_eliminate_eq(type, &(*ep1)->right.expr, ep2);
return;
}
- if (e2->type == type) {
- __expr_eliminate_eq(type, &e1, &e2->left.expr);
- __expr_eliminate_eq(type, &e1, &e2->right.expr);
+ if ((*ep2)->type == type) {
+ __expr_eliminate_eq(type, ep1, &(*ep2)->left.expr);
+ __expr_eliminate_eq(type, ep1, &(*ep2)->right.expr);
return;
}
- /* e1 and e2 are leaves. Compare them. */
+ /* *ep1 and *ep2 are leaves. Compare them. */
- if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
- e1->left.sym == e2->left.sym &&
- (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
+ if ((*ep1)->type == E_SYMBOL && (*ep2)->type == E_SYMBOL &&
+ (*ep1)->left.sym == (*ep2)->left.sym &&
+ ((*ep1)->left.sym == &symbol_yes || (*ep1)->left.sym == &symbol_no))
return;
- if (!expr_eq(e1, e2))
+ if (!expr_eq(*ep1, *ep2))
return;
- /* e1 and e2 are equal leaves. Prepare them for elimination. */
+ /* *ep1 and *ep2 are equal leaves. Prepare them for elimination. */
trans_count++;
- expr_free(e1); expr_free(e2);
+ expr_free(*ep1); expr_free(*ep2);
switch (type) {
case E_OR:
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = expr_alloc_symbol(&symbol_no);
+ *ep1 = expr_alloc_symbol(&symbol_no);
+ *ep2 = expr_alloc_symbol(&symbol_no);
break;
case E_AND:
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = expr_alloc_symbol(&symbol_yes);
+ *ep1 = expr_alloc_symbol(&symbol_yes);
+ *ep2 = expr_alloc_symbol(&symbol_yes);
break;
default:
;
@@ -220,29 +216,26 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
*/
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
{
- if (!e1 || !e2)
+ if (!*ep1 || !*ep2)
return;
- switch (e1->type) {
+ switch ((*ep1)->type) {
case E_OR:
case E_AND:
- __expr_eliminate_eq(e1->type, ep1, ep2);
+ __expr_eliminate_eq((*ep1)->type, ep1, ep2);
default:
;
}
- if (e1->type != e2->type) switch (e2->type) {
+ if ((*ep1)->type != (*ep2)->type) switch ((*ep2)->type) {
case E_OR:
case E_AND:
- __expr_eliminate_eq(e2->type, ep1, ep2);
+ __expr_eliminate_eq((*ep2)->type, ep1, ep2);
default:
;
}
- e1 = expr_eliminate_yn(e1);
- e2 = expr_eliminate_yn(e2);
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
}
-#undef e1
-#undef e2
-
/*
* Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
* &&/|| expressions are considered equal if every operand in one expression
@@ -286,7 +279,6 @@ int expr_eq(struct expr *e1, struct expr *e2)
expr_free(e2);
trans_count = old_count;
return res;
- case E_LIST:
case E_RANGE:
case E_NONE:
/* panic */;
@@ -566,59 +558,55 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
*/
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
-#define e1 (*ep1)
-#define e2 (*ep2)
struct expr *tmp;
/* Recurse down to leaves */
- if (e1->type == type) {
- expr_eliminate_dups1(type, &e1->left.expr, &e2);
- expr_eliminate_dups1(type, &e1->right.expr, &e2);
+ if ((*ep1)->type == type) {
+ expr_eliminate_dups1(type, &(*ep1)->left.expr, ep2);
+ expr_eliminate_dups1(type, &(*ep1)->right.expr, ep2);
return;
}
- if (e2->type == type) {
- expr_eliminate_dups1(type, &e1, &e2->left.expr);
- expr_eliminate_dups1(type, &e1, &e2->right.expr);
+ if ((*ep2)->type == type) {
+ expr_eliminate_dups1(type, ep1, &(*ep2)->left.expr);
+ expr_eliminate_dups1(type, ep1, &(*ep2)->right.expr);
return;
}
- /* e1 and e2 are leaves. Compare and process them. */
+ /* *ep1 and *ep2 are leaves. Compare and process them. */
- if (e1 == e2)
+ if (*ep1 == *ep2)
return;
- switch (e1->type) {
+ switch ((*ep1)->type) {
case E_OR: case E_AND:
- expr_eliminate_dups1(e1->type, &e1, &e1);
+ expr_eliminate_dups1((*ep1)->type, ep1, ep1);
default:
;
}
switch (type) {
case E_OR:
- tmp = expr_join_or(e1, e2);
+ tmp = expr_join_or(*ep1, *ep2);
if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = tmp;
+ expr_free(*ep1); expr_free(*ep2);
+ *ep1 = expr_alloc_symbol(&symbol_no);
+ *ep2 = tmp;
trans_count++;
}
break;
case E_AND:
- tmp = expr_join_and(e1, e2);
+ tmp = expr_join_and(*ep1, *ep2);
if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = tmp;
+ expr_free(*ep1); expr_free(*ep2);
+ *ep1 = expr_alloc_symbol(&symbol_yes);
+ *ep2 = tmp;
trans_count++;
}
break;
default:
;
}
-#undef e1
-#undef e2
}
/*
@@ -639,7 +627,7 @@ struct expr *expr_eliminate_dups(struct expr *e)
return e;
oldcount = trans_count;
- while (1) {
+ do {
trans_count = 0;
switch (e->type) {
case E_OR: case E_AND:
@@ -647,11 +635,8 @@ struct expr *expr_eliminate_dups(struct expr *e)
default:
;
}
- if (!trans_count)
- /* No simplifications done in this pass. We're done */
- break;
e = expr_eliminate_yn(e);
- }
+ } while (trans_count); /* repeat until we get no more simplifications */
trans_count = oldcount;
return e;
}
@@ -676,7 +661,6 @@ struct expr *expr_transform(struct expr *e)
case E_LTH:
case E_UNEQUAL:
case E_SYMBOL:
- case E_LIST:
break;
default:
e->left.expr = expr_transform(e->left.expr);
@@ -947,7 +931,6 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
break;
case E_SYMBOL:
return expr_alloc_comp(type, e->left.sym, sym);
- case E_LIST:
case E_RANGE:
case E_NONE:
/* panic */;
@@ -1083,29 +1066,27 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
case E_GTH:
if (t2 == E_EQUAL || t2 == E_UNEQUAL)
return 1;
+ /* fallthrough */
case E_EQUAL:
case E_UNEQUAL:
if (t2 == E_NOT)
return 1;
+ /* fallthrough */
case E_NOT:
if (t2 == E_AND)
return 1;
+ /* fallthrough */
case E_AND:
if (t2 == E_OR)
return 1;
- case E_OR:
- if (t2 == E_LIST)
- return 1;
- case E_LIST:
- if (t2 == 0)
- return 1;
+ /* fallthrough */
default:
- return -1;
+ break;
}
return 0;
}
-void expr_print(struct expr *e,
+void expr_print(const struct expr *e,
void (*fn)(void *, struct symbol *, const char *),
void *data, int prevtoken)
{
@@ -1171,13 +1152,6 @@ void expr_print(struct expr *e,
fn(data, NULL, " && ");
expr_print(e->right.expr, fn, data, E_AND);
break;
- case E_LIST:
- fn(data, e->right.sym, e->right.sym->name);
- if (e->left.expr) {
- fn(data, NULL, " ^ ");
- expr_print(e->left.expr, fn, data, E_LIST);
- }
- break;
case E_RANGE:
fn(data, NULL, "[");
fn(data, e->left.sym, e->left.sym->name);
@@ -1237,7 +1211,7 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
str_printf(gs, " [=%s]", sym_str);
}
-void expr_gstr_print(struct expr *e, struct gstr *gs)
+void expr_gstr_print(const struct expr *e, struct gstr *gs)
{
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 7c0c242318bc..2bc96cd28253 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -12,12 +12,11 @@ extern "C" {
#include <assert.h>
#include <stdio.h>
-#include "list_types.h"
#ifndef __cplusplus
#include <stdbool.h>
#endif
-#include "list_types.h"
+#include <list_types.h>
typedef enum tristate {
no, mod, yes
@@ -26,7 +25,7 @@ typedef enum tristate {
enum expr_type {
E_NONE, E_OR, E_AND, E_NOT,
E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,
- E_LIST, E_SYMBOL, E_RANGE
+ E_SYMBOL, E_RANGE
};
union expr_data {
@@ -43,9 +42,6 @@ struct expr {
#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
#define EXPR_NOT(dep) (2-(dep))
-#define expr_list_for_each_sym(l, e, s) \
- for (e = (l); e && (s = e->right.sym); e = e->left.expr)
-
struct expr_value {
struct expr *expr;
tristate tri;
@@ -73,6 +69,8 @@ enum {
* Represents a configuration symbol.
*
* Choices are represented as a special kind of symbol with null name.
+ *
+ * @choice_link: linked to menu::choice_members
*/
struct symbol {
/* link node for the hash table */
@@ -110,6 +108,8 @@ struct symbol {
/* config entries associated with this symbol */
struct list_head menus;
+ struct list_head choice_link;
+
/* SYMBOL_* flags */
int flags;
@@ -130,10 +130,8 @@ struct symbol {
#define SYMBOL_CONST 0x0001 /* symbol is const */
#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
-#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
-#define SYMBOL_CHANGED 0x0400 /* ? */
#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */
#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
#define SYMBOL_WARNED 0x8000 /* warning has been issued */
@@ -145,9 +143,6 @@ struct symbol {
#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
-/* choice values need to be set before calculating this symbol value */
-#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000
-
#define SYMBOL_MAXLENGTH 256
/* A property represent the config options that can be associated
@@ -170,7 +165,6 @@ enum prop_type {
P_COMMENT, /* text associated with a comment */
P_MENU, /* prompt associated with a menu or menuconfig symbol */
P_DEFAULT, /* default y */
- P_CHOICE, /* choice value */
P_SELECT, /* select BAR */
P_IMPLY, /* imply BAR */
P_RANGE, /* range 7..100 (for a symbol) */
@@ -184,7 +178,7 @@ struct property {
struct expr_value visible;
struct expr *expr; /* the optional conditional part of the property */
struct menu *menu; /* the menu the property are associated with
- * valid for: P_SELECT, P_RANGE, P_CHOICE,
+ * valid for: P_SELECT, P_RANGE,
* P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
const char *filename; /* what file was this property defined */
int lineno; /* what lineno was this property defined */
@@ -194,7 +188,6 @@ struct property {
for (st = sym->prop; st; st = st->next) \
if (st->type == (tok))
#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
-#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
#define for_all_prompts(sym, st) \
for (st = sym->prop; st; st = st->next) \
if (st->text)
@@ -204,6 +197,8 @@ struct property {
* for all front ends). Each symbol, menu, etc. defined in the Kconfig files
* gets a node. A symbol defined in multiple locations gets one node at each
* location.
+ *
+ * @choice_members: list of choice members with priority.
*/
struct menu {
/* The next menu node at the same level */
@@ -223,6 +218,8 @@ struct menu {
struct list_head link; /* link to symbol::menus */
+ struct list_head choice_members;
+
/*
* The prompt associated with the node. This holds the prompt for a
* symbol as well as the text for a menu or comment, along with the
@@ -292,11 +289,11 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb
void expr_fprint(struct expr *e, FILE *out);
struct gstr; /* forward */
-void expr_gstr_print(struct expr *e, struct gstr *gs);
+void expr_gstr_print(const struct expr *e, struct gstr *gs);
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
tristate pr_type, const char *title);
-static inline int expr_is_yes(struct expr *e)
+static inline int expr_is_yes(const struct expr *e)
{
return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
}
diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
index 040d8f338820..fc954c0538fa 100755
--- a/scripts/kconfig/gconf-cfg.sh
+++ b/scripts/kconfig/gconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index e04dbafd3add..c0f46f189060 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -65,9 +65,6 @@ static void display_list(void);
static void display_tree(struct menu *menu);
static void display_tree_part(void);
static void update_tree(struct menu *src, GtkTreeIter * dst);
-static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row);
-static gchar **fill_row(struct menu *menu);
-static void conf_changed(void);
static void replace_button_icon(GladeXML *xml, GdkDrawable *window,
GtkStyle *style, gchar *btn_name, gchar **xpm)
@@ -87,6 +84,12 @@ static void replace_button_icon(GladeXML *xml, GdkDrawable *window,
gtk_tool_button_set_icon_widget(button, image);
}
+static void conf_changed(bool dirty)
+{
+ gtk_widget_set_sensitive(save_btn, dirty);
+ gtk_widget_set_sensitive(save_menu_item, dirty);
+}
+
/* Main Window Initialization */
static void init_main_window(const gchar *glade_file)
{
@@ -1051,7 +1054,7 @@ static gchar **fill_row(struct menu *menu)
if (sym_is_choice(sym)) { // parse childs for getting final value
struct menu *child;
- struct symbol *def_sym = sym_get_choice_value(sym);
+ struct symbol *def_sym = sym_calc_choice(menu);
struct menu *def_menu = NULL;
for (child = menu->list; child; child = child->next) {
@@ -1064,12 +1067,10 @@ static gchar **fill_row(struct menu *menu)
row[COL_VALUE] =
g_strdup(menu_get_prompt(def_menu));
- if (sym_get_type(sym) == S_BOOLEAN) {
- row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
- return row;
- }
+ row[COL_BTNVIS] = GINT_TO_POINTER(FALSE);
+ return row;
}
- if (sym->flags & SYMBOL_CHOICEVAL)
+ if (sym_is_choice_value(sym))
row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
stype = sym_get_type(sym);
@@ -1447,10 +1448,3 @@ int main(int ac, char *av[])
return 0;
}
-
-static void conf_changed(void)
-{
- bool changed = conf_get_changed();
- gtk_widget_set_sensitive(save_btn, changed);
- gtk_widget_set_sensitive(save_menu_item, changed);
-}
diff --git a/scripts/kconfig/internal.h b/scripts/kconfig/internal.h
index 6c721c4cfd72..02106eb7815e 100644
--- a/scripts/kconfig/internal.h
+++ b/scripts/kconfig/internal.h
@@ -2,7 +2,7 @@
#ifndef INTERNAL_H
#define INTERNAL_H
-#include "hashtable.h"
+#include <hashtable.h>
#define SYMBOL_HASHSIZE (1U << 14)
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 64dfc354dd5c..401bdf36323a 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -40,7 +40,6 @@ void zconf_nextfile(const char *name);
/* confdata.c */
extern struct gstr autoconf_cmd;
const char *conf_get_configname(void);
-void set_all_choice_values(struct symbol *csym);
/* confdata.c and expr.c */
static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
@@ -76,7 +75,7 @@ struct gstr str_new(void);
void str_free(struct gstr *gs);
void str_append(struct gstr *gs, const char *s);
void str_printf(struct gstr *gs, const char *fmt, ...);
-char *str_get(struct gstr *gs);
+char *str_get(const struct gstr *gs);
/* menu.c */
struct menu *menu_next(struct menu *menu, struct menu *root);
@@ -85,13 +84,14 @@ struct menu *menu_next(struct menu *menu, struct menu *root);
#define menu_for_each_entry(menu) \
menu_for_each_sub_entry(menu, &rootmenu)
void _menu_init(void);
-void menu_warn(struct menu *menu, const char *fmt, ...);
+void menu_warn(const struct menu *menu, const char *fmt, ...);
struct menu *menu_add_menu(void);
void menu_end_menu(void);
void menu_add_entry(struct symbol *sym);
void menu_add_dep(struct expr *dep);
void menu_add_visibility(struct expr *dep);
-struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, const char *prompt,
+ struct expr *dep);
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
void menu_finalize(void);
@@ -101,8 +101,8 @@ extern struct menu rootmenu;
bool menu_is_empty(struct menu *menu);
bool menu_is_visible(struct menu *menu);
-bool menu_has_prompt(struct menu *menu);
-const char *menu_get_prompt(struct menu *menu);
+bool menu_has_prompt(const struct menu *menu);
+const char *menu_get_prompt(const struct menu *menu);
struct menu *menu_get_parent_menu(struct menu *menu);
int get_jump_key_char(void);
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
@@ -110,35 +110,27 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help);
/* symbol.c */
void sym_clear_all_valid(void);
-struct symbol *sym_choice_default(struct symbol *sym);
+struct symbol *sym_choice_default(struct menu *choice);
+struct symbol *sym_calc_choice(struct menu *choice);
struct property *sym_get_range_prop(struct symbol *sym);
const char *sym_get_string_default(struct symbol *sym);
struct symbol *sym_check_deps(struct symbol *sym);
-struct symbol *prop_get_symbol(struct property *prop);
+struct symbol *prop_get_symbol(const struct property *prop);
-static inline tristate sym_get_tristate_value(struct symbol *sym)
+static inline tristate sym_get_tristate_value(const struct symbol *sym)
{
return sym->curr.tri;
}
-
-static inline struct symbol *sym_get_choice_value(struct symbol *sym)
-{
- return (struct symbol *)sym->curr.val;
-}
-
-static inline bool sym_is_choice(struct symbol *sym)
+static inline bool sym_is_choice(const struct symbol *sym)
{
/* A choice is a symbol with no name */
return sym->name == NULL;
}
-static inline bool sym_is_choice_value(struct symbol *sym)
-{
- return sym->flags & SYMBOL_CHOICEVAL ? true : false;
-}
+bool sym_is_choice_value(const struct symbol *sym);
-static inline bool sym_has_value(struct symbol *sym)
+static inline bool sym_has_value(const struct symbol *sym)
{
return sym->flags & SYMBOL_DEF_USER ? true : false;
}
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index d76aaf4ea117..63519cd24bc7 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -13,7 +13,7 @@ int conf_write(const char *name);
int conf_write_autoconf(int overwrite);
void conf_set_changed(bool val);
bool conf_get_changed(void);
-void conf_set_changed_callback(void (*fn)(void));
+void conf_set_changed_callback(void (*fn)(bool));
void conf_set_message_callback(void (*fn)(const char *s));
bool conf_errors(void);
@@ -25,21 +25,23 @@ struct symbol ** sym_re_search(const char *pattern);
const char * sym_type_name(enum symbol_type type);
void sym_calc_value(struct symbol *sym);
bool sym_dep_errors(void);
-enum symbol_type sym_get_type(struct symbol *sym);
-bool sym_tristate_within_range(struct symbol *sym,tristate tri);
+enum symbol_type sym_get_type(const struct symbol *sym);
+bool sym_tristate_within_range(const struct symbol *sym, tristate tri);
bool sym_set_tristate_value(struct symbol *sym,tristate tri);
+void choice_set_value(struct menu *choice, struct symbol *sym);
tristate sym_toggle_tristate_value(struct symbol *sym);
bool sym_string_valid(struct symbol *sym, const char *newval);
bool sym_string_within_range(struct symbol *sym, const char *str);
bool sym_set_string_value(struct symbol *sym, const char *newval);
-bool sym_is_changeable(struct symbol *sym);
-struct property * sym_get_choice_prop(struct symbol *sym);
-struct menu *sym_get_choice_menu(struct symbol *sym);
+bool sym_is_changeable(const struct symbol *sym);
+struct menu *sym_get_choice_menu(const struct symbol *sym);
const char * sym_get_string_value(struct symbol *sym);
const char * prop_get_type_name(enum prop_type type);
/* expr.c */
-void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
+void expr_print(const struct expr *e,
+ void (*fn)(void *, struct symbol *, const char *),
+ void *data, int prevtoken);
#endif /* LKC_PROTO_H */
diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
index 1e61f50a5905..1bc304dc2f7d 100755
--- a/scripts/kconfig/mconf-cfg.sh
+++ b/scripts/kconfig/mconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index d6a61ca1a984..3887eac75289 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -19,7 +19,7 @@
#include <signal.h>
#include <unistd.h>
-#include "list.h"
+#include <list.h>
#include "lkc.h"
#include "lxdialog/dialog.h"
#include "mnconf-common.h"
@@ -514,7 +514,7 @@ static void build_conf(struct menu *menu)
type = sym_get_type(sym);
if (sym_is_choice(sym)) {
- struct symbol *def_sym = sym_get_choice_value(sym);
+ struct symbol *def_sym = sym_calc_choice(menu);
struct menu *def_menu = NULL;
child_count++;
@@ -523,28 +523,14 @@ static void build_conf(struct menu *menu)
def_menu = child;
}
- val = sym_get_tristate_value(sym);
- if (sym_is_changeable(sym)) {
- switch (val) {
- case yes: ch = '*'; break;
- case mod: ch = 'M'; break;
- default: ch = ' '; break;
- }
- item_make("<%c>", ch);
- item_set_tag('t');
- item_set_data(menu);
- } else {
- item_make(" ");
- item_set_tag(def_menu ? 't' : ':');
- item_set_data(menu);
- }
+ item_make(" ");
+ item_set_tag(def_menu ? 't' : ':');
+ item_set_data(menu);
item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
- if (val == yes) {
- if (def_menu)
- item_add_str(" (%s) --->", menu_get_prompt(def_menu));
- return;
- }
+ if (def_menu)
+ item_add_str(" (%s) --->", menu_get_prompt(def_menu));
+ return;
} else {
if (menu == current_menu) {
item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
@@ -614,7 +600,7 @@ static void conf_choice(struct menu *menu)
struct menu *child;
struct symbol *active;
- active = sym_get_choice_value(menu->sym);
+ active = sym_calc_choice(menu);
while (1) {
int res;
int selected;
@@ -633,7 +619,7 @@ static void conf_choice(struct menu *menu)
item_set_data(child);
if (child->sym == active)
item_set_selected(1);
- if (child->sym == sym_get_choice_value(menu->sym))
+ if (child->sym == sym_calc_choice(menu))
item_set_tag('X');
}
dialog_clear();
@@ -650,7 +636,7 @@ static void conf_choice(struct menu *menu)
if (!child->sym)
break;
- sym_set_tristate_value(child->sym, yes);
+ choice_set_value(menu, child->sym);
}
return;
case 1:
@@ -814,7 +800,7 @@ static void conf(struct menu *menu, struct menu *active_menu)
conf(submenu, NULL);
break;
case 't':
- if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+ if (sym_is_choice(sym))
conf_choice(submenu);
else if (submenu->prompt->type == P_MENU)
conf(submenu, NULL);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index eef9b63cdf11..323cc0b62be6 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -8,9 +8,9 @@
#include <stdlib.h>
#include <string.h>
+#include <list.h>
#include "lkc.h"
#include "internal.h"
-#include "list.h"
static const char nohelp_text[] = "There is no help available for this option.";
@@ -38,7 +38,7 @@ struct menu *menu_next(struct menu *menu, struct menu *root)
return menu->next;
}
-void menu_warn(struct menu *menu, const char *fmt, ...)
+void menu_warn(const struct menu *menu, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -48,7 +48,7 @@ void menu_warn(struct menu *menu, const char *fmt, ...)
va_end(ap);
}
-static void prop_warn(struct property *prop, const char *fmt, ...)
+static void prop_warn(const struct property *prop, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -175,7 +175,7 @@ static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
return prop;
}
-struct property *menu_add_prompt(enum prop_type type, char *prompt,
+struct property *menu_add_prompt(enum prop_type type, const char *prompt,
struct expr *dep)
{
struct property *prop = menu_add_prop(type, NULL, dep);
@@ -306,7 +306,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
struct menu *menu, *last_menu;
struct symbol *sym;
struct property *prop;
- struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+ struct expr *basedep, *dep, *dep2;
sym = parent->sym;
if (parent->list) {
@@ -315,35 +315,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
* and propagate parent dependencies before moving on.
*/
- bool is_choice = false;
-
- if (sym && sym_is_choice(sym))
- is_choice = true;
-
- if (is_choice) {
- if (sym->type == S_UNKNOWN) {
- /* find the first choice value to find out choice type */
- current_entry = parent;
- for (menu = parent->list; menu; menu = menu->next) {
- if (menu->sym && menu->sym->type != S_UNKNOWN) {
- menu_set_type(menu->sym->type);
- break;
- }
- }
- }
-
- /*
- * Use the choice itself as the parent dependency of
- * the contained items. This turns the mode of the
- * choice into an upper bound on the visibility of the
- * choice value symbols.
- */
- parentdep = expr_alloc_symbol(sym);
- } else {
- /* Menu node for 'menu', 'if' */
- parentdep = parent->dep;
- }
-
/* For each child menu node... */
for (menu = parent->list; menu; menu = menu->next) {
/*
@@ -352,7 +323,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
basedep = rewrite_m(menu->dep);
basedep = expr_transform(basedep);
- basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_alloc_and(expr_copy(parent->dep), basedep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
@@ -416,15 +387,12 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
}
}
- if (is_choice)
- expr_free(parentdep);
-
/*
* Recursively process children in the same fashion before
* moving on
*/
for (menu = parent->list; menu; menu = menu->next)
- _menu_finalize(menu, is_choice);
+ _menu_finalize(menu, sym && sym_is_choice(sym));
} else if (!inside_choice && sym) {
/*
* Automatic submenu creation. If sym is a symbol and A, B, C,
@@ -499,34 +467,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
}
for (menu = parent->list; menu; menu = menu->next) {
- if (sym && sym_is_choice(sym) &&
- menu->sym && !sym_is_choice_value(menu->sym)) {
- current_entry = menu;
- menu->sym->flags |= SYMBOL_CHOICEVAL;
- /* Non-tristate choice values of tristate choices must
- * depend on the choice being set to Y. The choice
- * values' dependencies were propagated to their
- * properties above, so the change here must be re-
- * propagated.
- */
- if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
- basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
- menu->dep = expr_alloc_and(basedep, menu->dep);
- for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->menu != menu)
- continue;
- prop->visible.expr = expr_alloc_and(expr_copy(basedep),
- prop->visible.expr);
- }
- }
- menu_add_symbol(P_CHOICE, sym, NULL);
- prop = sym_get_choice_prop(sym);
- for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
- ;
- *ep = expr_alloc_one(E_LIST, NULL);
- (*ep)->right.sym = menu->sym;
- }
-
/*
* This code serves two purposes:
*
@@ -575,17 +515,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
sym_check_prop(sym);
sym->flags |= SYMBOL_WARNED;
}
-
- /*
- * For choices, add a reverse dependency (corresponding to a select) of
- * '<visibility> && m'. This prevents the user from setting the choice
- * mode to 'n' when the choice is visible.
- */
- if (sym && sym_is_choice(sym) && parent->prompt) {
- sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
- expr_alloc_and(parent->prompt->visible.expr,
- expr_alloc_symbol(&symbol_mod)));
- }
}
void menu_finalize(void)
@@ -593,7 +522,7 @@ void menu_finalize(void)
_menu_finalize(&rootmenu, false);
}
-bool menu_has_prompt(struct menu *menu)
+bool menu_has_prompt(const struct menu *menu)
{
if (!menu->prompt)
return false;
@@ -618,7 +547,6 @@ bool menu_is_empty(struct menu *menu)
bool menu_is_visible(struct menu *menu)
{
- struct menu *child;
struct symbol *sym;
tristate visible;
@@ -637,24 +565,10 @@ bool menu_is_visible(struct menu *menu)
} else
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
- if (visible != no)
- return true;
-
- if (!sym || sym_get_tristate_value(menu->sym) == no)
- return false;
-
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)) {
- if (sym)
- sym->flags |= SYMBOL_DEF_USER;
- return true;
- }
- }
-
- return false;
+ return visible != no;
}
-const char *menu_get_prompt(struct menu *menu)
+const char *menu_get_prompt(const struct menu *menu)
{
if (menu->prompt)
return menu->prompt->text;
@@ -675,13 +589,14 @@ struct menu *menu_get_parent_menu(struct menu *menu)
return menu;
}
-static void get_def_str(struct gstr *r, struct menu *menu)
+static void get_def_str(struct gstr *r, const struct menu *menu)
{
str_printf(r, "Defined at %s:%d\n",
menu->filename, menu->lineno);
}
-static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
+static void get_dep_str(struct gstr *r, const struct expr *expr,
+ const char *prefix)
{
if (!expr_is_yes(expr)) {
str_append(r, prefix);
diff --git a/scripts/kconfig/mnconf-common.c b/scripts/kconfig/mnconf-common.c
index 18cb9a6c5aaa..8e24b07121df 100644
--- a/scripts/kconfig/mnconf-common.c
+++ b/scripts/kconfig/mnconf-common.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <list.h>
#include "expr.h"
-#include "list.h"
#include "mnconf-common.h"
int jump_key_char;
diff --git a/scripts/kconfig/mnconf-common.h b/scripts/kconfig/mnconf-common.h
index ab6292cc4bf2..53bd7292e931 100644
--- a/scripts/kconfig/mnconf-common.h
+++ b/scripts/kconfig/mnconf-common.h
@@ -4,6 +4,8 @@
#include <stddef.h>
+#include <list_types.h>
+
struct search_data {
struct list_head *head;
struct menu *target;
diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
index f871a2160e36..a20290b1a37d 100755
--- a/scripts/kconfig/nconf-cfg.sh
+++ b/scripts/kconfig/nconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index e1cb09418cbe..b91ca47e9e9a 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -11,7 +11,7 @@
#include <strings.h>
#include <stdlib.h>
-#include "list.h"
+#include <list.h>
#include "lkc.h"
#include "mnconf-common.h"
#include "nconf.h"
@@ -815,7 +815,7 @@ static void build_conf(struct menu *menu)
type = sym_get_type(sym);
if (sym_is_choice(sym)) {
- struct symbol *def_sym = sym_get_choice_value(sym);
+ struct symbol *def_sym = sym_calc_choice(menu);
struct menu *def_menu = NULL;
child_count++;
@@ -825,30 +825,13 @@ static void build_conf(struct menu *menu)
}
val = sym_get_tristate_value(sym);
- if (sym_is_changeable(sym)) {
- switch (val) {
- case yes:
- ch = '*';
- break;
- case mod:
- ch = 'M';
- break;
- default:
- ch = ' ';
- break;
- }
- item_make(menu, 't', "<%c>", ch);
- } else {
- item_make(menu, def_menu ? 't' : ':', " ");
- }
+ item_make(menu, def_menu ? 't' : ':', " ");
item_add_str("%*c%s", indent + 1,
' ', menu_get_prompt(menu));
- if (val == yes) {
- if (def_menu)
- item_add_str(" (%s) --->", menu_get_prompt(def_menu));
- return;
- }
+ if (def_menu)
+ item_add_str(" (%s) --->", menu_get_prompt(def_menu));
+ return;
} else {
if (menu == current_menu) {
item_make(menu, ':',
@@ -1191,8 +1174,7 @@ static void selected_conf(struct menu *menu, struct menu *active_menu)
conf(submenu);
break;
case 't':
- if (sym_is_choice(sym) &&
- sym_get_tristate_value(sym) == yes)
+ if (sym_is_choice(sym))
conf_choice(submenu);
else if (submenu->prompt &&
submenu->prompt->type == P_MENU)
@@ -1257,7 +1239,7 @@ static void conf_choice(struct menu *menu)
.pattern = "",
};
- active = sym_get_choice_value(menu->sym);
+ active = sym_calc_choice(menu);
/* this is mostly duplicated from the conf() function. */
while (!global_exit) {
reset_menu();
@@ -1266,7 +1248,7 @@ static void conf_choice(struct menu *menu)
if (!show_all_items && !menu_is_visible(child))
continue;
- if (child->sym == sym_get_choice_value(menu->sym))
+ if (child->sym == sym_calc_choice(menu))
item_make(child, ':', "<X> %s",
menu_get_prompt(child));
else if (child->sym)
@@ -1349,7 +1331,7 @@ static void conf_choice(struct menu *menu)
case ' ':
case 10:
case KEY_RIGHT:
- sym_set_tristate_value(child->sym, yes);
+ choice_set_value(menu, child->sym);
return;
case 'h':
case '?':
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index ff709001b1f0..61900feb4254 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -28,9 +28,7 @@ static void zconf_error(const char *err, ...);
static bool zconf_endtoken(const char *tokenname,
const char *expected_tokenname);
-struct menu *current_menu, *current_entry;
-
-static bool inside_choice = false;
+struct menu *current_menu, *current_entry, *current_choice;
%}
@@ -90,7 +88,7 @@ static bool inside_choice = false;
%type <symbol> nonconst_symbol
%type <symbol> symbol
-%type <type> type logic_type default
+%type <type> type default
%type <expr> expr
%type <expr> if_expr
%type <string> end
@@ -147,12 +145,21 @@ config_entry_start: T_CONFIG nonconst_symbol T_EOL
config_stmt: config_entry_start config_option_list
{
- if (inside_choice) {
+ if (current_choice) {
if (!current_entry->prompt) {
fprintf(stderr, "%s:%d: error: choice member must have a prompt\n",
current_entry->filename, current_entry->lineno);
yynerrs++;
}
+
+ if (current_entry->sym->type != S_BOOLEAN) {
+ fprintf(stderr, "%s:%d: error: choice member must be bool\n",
+ current_entry->filename, current_entry->lineno);
+ yynerrs++;
+ }
+
+ list_add_tail(&current_entry->sym->choice_link,
+ &current_choice->choice_members);
}
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
@@ -234,7 +241,9 @@ choice: T_CHOICE T_EOL
struct symbol *sym = sym_lookup(NULL, 0);
menu_add_entry(sym);
- menu_add_expr(P_CHOICE, NULL, NULL);
+ menu_set_type(S_BOOLEAN);
+ INIT_LIST_HEAD(&current_entry->choice_members);
+
printd(DEBUG_PARSE, "%s:%d:choice\n", cur_filename, cur_lineno);
};
@@ -248,12 +257,12 @@ choice_entry: choice choice_option_list
$$ = menu_add_menu();
- inside_choice = true;
+ current_choice = current_entry;
};
choice_end: end
{
- inside_choice = false;
+ current_choice = NULL;
if (zconf_endtoken($1, "choice")) {
menu_end_menu();
@@ -277,10 +286,10 @@ choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
-choice_option: logic_type prompt_stmt_opt T_EOL
+choice_option: T_BOOL T_WORD_QUOTE if_expr T_EOL
{
- menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
+ menu_add_prompt(P_PROMPT, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:bool\n", cur_filename, cur_lineno);
};
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
@@ -290,15 +299,12 @@ choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
};
type:
- logic_type
+ T_BOOL { $$ = S_BOOLEAN; }
+ | T_TRISTATE { $$ = S_TRISTATE; }
| T_INT { $$ = S_INT; }
| T_HEX { $$ = S_HEX; }
| T_STRING { $$ = S_STRING; }
-logic_type:
- T_BOOL { $$ = S_BOOLEAN; }
- | T_TRISTATE { $$ = S_TRISTATE; }
-
default:
T_DEFAULT { $$ = S_UNKNOWN; }
| T_DEF_BOOL { $$ = S_BOOLEAN; }
@@ -483,7 +489,7 @@ assign_val:
*
* Return: -1 if an error is found, 0 otherwise.
*/
-static int choice_check_sanity(struct menu *menu)
+static int choice_check_sanity(const struct menu *menu)
{
struct property *prop;
int ret = 0;
@@ -638,7 +644,7 @@ static void print_quoted_string(FILE *out, const char *str)
putc('"', out);
}
-static void print_symbol(FILE *out, struct menu *menu)
+static void print_symbol(FILE *out, const struct menu *menu)
{
struct symbol *sym = menu->sym;
struct property *prop;
@@ -689,9 +695,6 @@ static void print_symbol(FILE *out, struct menu *menu)
}
fputc('\n', out);
break;
- case P_CHOICE:
- fputs(" #choice value\n", out);
- break;
case P_SELECT:
fputs( " select ", out);
expr_fprint(prop->expr, out);
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
index f0a4a218c4a5..67d1fb95c491 100644
--- a/scripts/kconfig/preprocess.c
+++ b/scripts/kconfig/preprocess.c
@@ -9,9 +9,9 @@
#include <stdlib.h>
#include <string.h>
-#include "array_size.h"
+#include <array_size.h>
+#include <list.h>
#include "internal.h"
-#include "list.h"
#include "lkc.h"
#include "preprocess.h"
diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
index 0e113b0f2455..bb2df66363a8 100755
--- a/scripts/kconfig/qconf-cfg.sh
+++ b/scripts/kconfig/qconf-cfg.sh
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
+set -eu
+
cflags=$1
libs=$2
bin=$3
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index c6c42c0f4e5d..7d239c032b3d 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -147,7 +147,7 @@ void ConfigItem::updateMenu(void)
expr = sym_get_tristate_value(sym);
switch (expr) {
case yes:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ if (sym_is_choice_value(sym))
setIcon(promptColIdx, choiceYesIcon);
else
setIcon(promptColIdx, symbolYesIcon);
@@ -1101,14 +1101,6 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
&stream, E_NONE);
stream << "<br>";
break;
- case P_CHOICE:
- if (sym_is_choice(sym)) {
- stream << "choice: ";
- expr_print(prop->expr, expr_print_help,
- &stream, E_NONE);
- stream << "<br>";
- }
- break;
default:
stream << "unknown property: ";
stream << prop_get_type_name(prop->type);
@@ -1397,8 +1389,6 @@ ConfigMainWindow::ConfigMainWindow(void)
conf_set_changed_callback(conf_changed);
- // Set saveAction's initial state
- conf_changed();
configname = xstrdup(conf_get_configname());
QAction *saveAsAction = new QAction("Save &As...", this);
@@ -1851,10 +1841,10 @@ void ConfigMainWindow::saveSettings(void)
configSettings->writeSizes("/split2", split2->sizes());
}
-void ConfigMainWindow::conf_changed(void)
+void ConfigMainWindow::conf_changed(bool dirty)
{
if (saveAction)
- saveAction->setEnabled(conf_get_changed());
+ saveAction->setEnabled(dirty);
}
void fixup_rootmenu(struct menu *menu)
@@ -1904,7 +1894,6 @@ int main(int ac, char** av)
conf_parse(name);
fixup_rootmenu(&rootmenu);
- conf_read(NULL);
//zconfdump(stdout);
configApp = new QApplication(ac, av);
@@ -1916,6 +1905,9 @@ int main(int ac, char** av)
//zconfdump(stdout);
configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
+
+ conf_read(NULL);
+
v->show();
configApp->exec();
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 78b0a1dfcd53..53373064d90a 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -239,7 +239,7 @@ class ConfigMainWindow : public QMainWindow {
char *configname;
static QAction *saveAction;
- static void conf_changed(void);
+ static void conf_changed(bool);
public:
ConfigMainWindow(void);
public slots:
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 0e439d3d48d1..71502abd3b12 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -40,16 +40,12 @@ struct symbol *modules_sym;
static tristate modules_val;
static int sym_warnings;
-enum symbol_type sym_get_type(struct symbol *sym)
+enum symbol_type sym_get_type(const struct symbol *sym)
{
enum symbol_type type = sym->type;
- if (type == S_TRISTATE) {
- if (sym_is_choice_value(sym) && sym->visible == yes)
- type = S_BOOLEAN;
- else if (modules_val == no)
- type = S_BOOLEAN;
- }
+ if (type == S_TRISTATE && modules_val == no)
+ type = S_BOOLEAN;
return type;
}
@@ -72,15 +68,6 @@ const char *sym_type_name(enum symbol_type type)
return "???";
}
-struct property *sym_get_choice_prop(struct symbol *sym)
-{
- struct property *prop;
-
- for_all_choices(sym, prop)
- return prop;
- return NULL;
-}
-
/**
* sym_get_choice_menu - get the parent choice menu if present
*
@@ -88,7 +75,7 @@ struct property *sym_get_choice_prop(struct symbol *sym)
*
* Return: a choice menu if this function is called against a choice member.
*/
-struct menu *sym_get_choice_menu(struct symbol *sym)
+struct menu *sym_get_choice_menu(const struct symbol *sym)
{
struct menu *menu = NULL;
struct menu *m;
@@ -192,7 +179,6 @@ static void sym_set_changed(struct symbol *sym)
{
struct menu *menu;
- sym->flags |= SYMBOL_CHANGED;
list_for_each_entry(menu, &sym->menus, link)
menu->flags |= MENU_CHANGED;
}
@@ -208,26 +194,12 @@ static void sym_set_all_changed(void)
static void sym_calc_visibility(struct symbol *sym)
{
struct property *prop;
- struct symbol *choice_sym = NULL;
tristate tri;
/* any prompt visible? */
tri = no;
-
- if (sym_is_choice_value(sym))
- choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
-
for_all_prompts(sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
- /*
- * Tristate choice_values with visibility 'mod' are
- * not visible if the corresponding choice's value is
- * 'yes'.
- */
- if (choice_sym && sym->type == S_TRISTATE &&
- prop->visible.tri == mod && choice_sym->curr.tri == yes)
- prop->visible.tri = no;
-
tri = EXPR_OR(tri, prop->visible.tri);
}
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
@@ -274,14 +246,14 @@ static void sym_calc_visibility(struct symbol *sym)
* Next locate the first visible choice value
* Return NULL if none was found
*/
-struct symbol *sym_choice_default(struct symbol *sym)
+struct symbol *sym_choice_default(struct menu *choice)
{
+ struct menu *menu;
struct symbol *def_sym;
struct property *prop;
- struct expr *e;
/* any of the defaults visible? */
- for_all_defaults(sym, prop) {
+ for_all_defaults(choice->sym, prop) {
prop->visible.tri = expr_calc_value(prop->visible.expr);
if (prop->visible.tri == no)
continue;
@@ -291,48 +263,99 @@ struct symbol *sym_choice_default(struct symbol *sym)
}
/* just get the first visible value */
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym)
- if (def_sym->visible != no)
- return def_sym;
+ menu_for_each_sub_entry(menu, choice)
+ if (menu->sym && menu->sym->visible != no)
+ return menu->sym;
/* failed to locate any defaults */
return NULL;
}
-static struct symbol *sym_calc_choice(struct symbol *sym)
+/*
+ * sym_calc_choice - calculate symbol values in a choice
+ *
+ * @choice: a menu of the choice
+ *
+ * Return: a chosen symbol
+ */
+struct symbol *sym_calc_choice(struct menu *choice)
{
- struct symbol *def_sym;
- struct property *prop;
- struct expr *e;
- int flags;
-
- /* first calculate all choice values' visibilities */
- flags = sym->flags;
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym) {
- sym_calc_visibility(def_sym);
- if (def_sym->visible != no)
- flags &= def_sym->flags;
+ struct symbol *res = NULL;
+ struct symbol *sym;
+ struct menu *menu;
+
+ /* Traverse the list of choice members in the priority order. */
+ list_for_each_entry(sym, &choice->choice_members, choice_link) {
+ sym_calc_visibility(sym);
+ if (sym->visible == no)
+ continue;
+
+ /* The first visible symble with the user value 'y'. */
+ if (sym_has_value(sym) && sym->def[S_DEF_USER].tri == yes) {
+ res = sym;
+ break;
+ }
}
- sym->flags &= flags | ~SYMBOL_DEF_USER;
+ /*
+ * If 'y' is not found in the user input, use the default, unless it is
+ * explicitly set to 'n'.
+ */
+ if (!res) {
+ res = sym_choice_default(choice);
+ if (res && sym_has_value(res) && res->def[S_DEF_USER].tri == no)
+ res = NULL;
+ }
- /* is the user choice visible? */
- def_sym = sym->def[S_DEF_USER].val;
- if (def_sym && def_sym->visible != no)
- return def_sym;
+ /* Still not found. Pick up the first visible, user-unspecified symbol. */
+ if (!res) {
+ menu_for_each_sub_entry(menu, choice) {
+ sym = menu->sym;
- def_sym = sym_choice_default(sym);
+ if (!sym || sym->visible == no || sym_has_value(sym))
+ continue;
- if (def_sym == NULL)
- /* no choice? reset tristate value */
- sym->curr.tri = no;
+ res = sym;
+ break;
+ }
+ }
+
+ /*
+ * Still not found. Traverse the linked list in the _reverse_ order to
+ * pick up the least prioritized 'n'.
+ */
+ if (!res) {
+ list_for_each_entry_reverse(sym, &choice->choice_members,
+ choice_link) {
+ if (sym->visible == no)
+ continue;
+
+ res = sym;
+ break;
+ }
+ }
+
+ menu_for_each_sub_entry(menu, choice) {
+ tristate val;
+
+ sym = menu->sym;
+
+ if (!sym || sym->visible == no)
+ continue;
+
+ val = sym == res ? yes : no;
+
+ if (sym->curr.tri != val)
+ sym_set_changed(sym);
+
+ sym->curr.tri = val;
+ sym->flags |= SYMBOL_VALID | SYMBOL_WRITE;
+ }
- return def_sym;
+ return res;
}
-static void sym_warn_unmet_dep(struct symbol *sym)
+static void sym_warn_unmet_dep(const struct symbol *sym)
{
struct gstr gs = str_new();
@@ -365,7 +388,7 @@ void sym_calc_value(struct symbol *sym)
{
struct symbol_value newval, oldval;
struct property *prop;
- struct expr *e;
+ struct menu *choice_menu;
if (!sym)
return;
@@ -373,13 +396,6 @@ void sym_calc_value(struct symbol *sym)
if (sym->flags & SYMBOL_VALID)
return;
- if (sym_is_choice_value(sym) &&
- sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
- sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
- prop = sym_get_choice_prop(sym);
- sym_calc_value(prop_get_symbol(prop));
- }
-
sym->flags |= SYMBOL_VALID;
oldval = sym->curr;
@@ -418,9 +434,11 @@ void sym_calc_value(struct symbol *sym)
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
- if (sym_is_choice_value(sym) && sym->visible == yes) {
- prop = sym_get_choice_prop(sym);
- newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
+ choice_menu = sym_get_choice_menu(sym);
+
+ if (choice_menu) {
+ sym_calc_choice(choice_menu);
+ newval.tri = sym->curr.tri;
} else {
if (sym->visible != no) {
/* if the symbol is visible use the user value
@@ -479,8 +497,6 @@ void sym_calc_value(struct symbol *sym)
}
sym->curr = newval;
- if (sym_is_choice(sym) && newval.tri == yes)
- sym->curr.val = sym_calc_choice(sym);
sym_validate_range(sym);
if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
@@ -491,23 +507,8 @@ void sym_calc_value(struct symbol *sym)
}
}
- if (sym_is_choice(sym)) {
- struct symbol *choice_sym;
-
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, choice_sym) {
- if ((sym->flags & SYMBOL_WRITE) &&
- choice_sym->visible != no)
- choice_sym->flags |= SYMBOL_WRITE;
- if (sym->flags & SYMBOL_CHANGED)
- sym_set_changed(choice_sym);
- }
-
+ if (sym_is_choice(sym))
sym->flags &= ~SYMBOL_WRITE;
- }
-
- if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
- set_all_choice_values(sym);
}
void sym_clear_all_valid(void)
@@ -520,7 +521,7 @@ void sym_clear_all_valid(void)
sym_calc_value(modules_sym);
}
-bool sym_tristate_within_range(struct symbol *sym, tristate val)
+bool sym_tristate_within_range(const struct symbol *sym, tristate val)
{
int type = sym_get_type(sym);
@@ -534,8 +535,6 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
- if (sym_is_choice_value(sym) && sym->visible == yes)
- return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
}
@@ -543,42 +542,75 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val)
{
tristate oldval = sym_get_tristate_value(sym);
- if (oldval != val && !sym_tristate_within_range(sym, val))
+ if (!sym_tristate_within_range(sym, val))
return false;
- if (!(sym->flags & SYMBOL_DEF_USER)) {
+ if (!(sym->flags & SYMBOL_DEF_USER) || sym->def[S_DEF_USER].tri != val) {
+ sym->def[S_DEF_USER].tri = val;
sym->flags |= SYMBOL_DEF_USER;
sym_set_changed(sym);
}
- /*
- * setting a choice value also resets the new flag of the choice
- * symbol and all other choice values.
- */
- if (sym_is_choice_value(sym) && val == yes) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- struct property *prop;
- struct expr *e;
-
- cs->def[S_DEF_USER].val = sym;
- cs->flags |= SYMBOL_DEF_USER;
- prop = sym_get_choice_prop(cs);
- for (e = prop->expr; e; e = e->left.expr) {
- if (e->right.sym->visible != no)
- e->right.sym->flags |= SYMBOL_DEF_USER;
- }
- }
- sym->def[S_DEF_USER].tri = val;
if (oldval != val)
sym_clear_all_valid();
return true;
}
+/**
+ * choice_set_value - set the user input to a choice
+ *
+ * @choice: menu entry for the choice
+ * @sym: selected symbol
+ */
+void choice_set_value(struct menu *choice, struct symbol *sym)
+{
+ struct menu *menu;
+ bool changed = false;
+
+ menu_for_each_sub_entry(menu, choice) {
+ tristate val;
+
+ if (!menu->sym)
+ continue;
+
+ if (menu->sym->visible == no)
+ continue;
+
+ val = menu->sym == sym ? yes : no;
+
+ if (menu->sym->curr.tri != val)
+ changed = true;
+
+ menu->sym->def[S_DEF_USER].tri = val;
+ menu->sym->flags |= SYMBOL_DEF_USER;
+
+ /*
+ * Now, the user has explicitly enabled or disabled this symbol,
+ * it should be given the highest priority. We are possibly
+ * setting multiple symbols to 'n', where the first symbol is
+ * given the least prioritized 'n'. This works well when the
+ * choice block ends up with selecting 'n' symbol.
+ * (see sym_calc_choice())
+ */
+ list_move(&menu->sym->choice_link, &choice->choice_members);
+ }
+
+ if (changed)
+ sym_clear_all_valid();
+}
+
tristate sym_toggle_tristate_value(struct symbol *sym)
{
+ struct menu *choice;
tristate oldval, newval;
+ choice = sym_get_choice_menu(sym);
+ if (choice) {
+ choice_set_value(choice, sym);
+ return yes;
+ }
+
oldval = newval = sym_get_tristate_value(sym);
do {
switch (newval) {
@@ -834,9 +866,14 @@ const char *sym_get_string_value(struct symbol *sym)
return (const char *)sym->curr.val;
}
-bool sym_is_changeable(struct symbol *sym)
+bool sym_is_changeable(const struct symbol *sym)
+{
+ return !sym_is_choice(sym) && sym->visible > sym->rev_dep.tri;
+}
+
+bool sym_is_choice_value(const struct symbol *sym)
{
- return sym->visible > sym->rev_dep.tri;
+ return !list_empty(&sym->choice_link);
}
HASHTABLE_DEFINE(sym_hashtable, SYMBOL_HASHSIZE);
@@ -876,6 +913,7 @@ struct symbol *sym_lookup(const char *name, int flags)
symbol->type = S_UNKNOWN;
symbol->flags = flags;
INIT_LIST_HEAD(&symbol->menus);
+ INIT_LIST_HEAD(&symbol->choice_link);
hash_add(sym_hashtable, &symbol->node, hash);
@@ -1036,13 +1074,14 @@ static void sym_check_print_recursive(struct symbol *last_sym)
{
struct dep_stack *stack;
struct symbol *sym, *next_sym;
- struct menu *menu = NULL;
- struct property *prop;
+ struct menu *choice;
struct dep_stack cv_stack;
+ enum prop_type type;
- if (sym_is_choice_value(last_sym)) {
+ choice = sym_get_choice_menu(last_sym);
+ if (choice) {
dep_stack_insert(&cv_stack, last_sym);
- last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
+ last_sym = choice->sym;
}
for (stack = check_top; stack != NULL; stack = stack->prev)
@@ -1056,59 +1095,37 @@ static void sym_check_print_recursive(struct symbol *last_sym)
for (; stack; stack = stack->next) {
sym = stack->sym;
next_sym = stack->next ? stack->next->sym : last_sym;
- prop = stack->prop;
- if (prop == NULL)
- prop = stack->sym->prop;
-
- /* for choice values find the menu entry (used below) */
- if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
- for (prop = sym->prop; prop; prop = prop->next) {
- menu = prop->menu;
- if (prop->menu)
- break;
- }
- }
+ type = stack->prop ? stack->prop->type : P_UNKNOWN;
+
if (stack->sym == last_sym)
- fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
- prop->filename, prop->lineno);
+ fprintf(stderr, "error: recursive dependency detected!\n");
- if (sym_is_choice(sym)) {
- fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
- menu->filename, menu->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (sym_is_choice_value(sym)) {
- fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
- menu->filename, menu->lineno,
+ if (sym_is_choice(next_sym)) {
+ choice = list_first_entry(&next_sym->menus, struct menu, link);
+
+ fprintf(stderr, "\tsymbol %s is part of choice block at %s:%d\n",
sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ choice->filename, choice->lineno);
} else if (stack->expr == &sym->dir_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
- prop->filename, prop->lineno,
+ fprintf(stderr, "\tsymbol %s depends on %s\n",
sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ next_sym->name);
} else if (stack->expr == &sym->rev_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
- prop->filename, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ fprintf(stderr, "\tsymbol %s is selected by %s\n",
+ sym->name, next_sym->name);
} else if (stack->expr == &sym->implied.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
- prop->filename, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
+ fprintf(stderr, "\tsymbol %s is implied by %s\n",
+ sym->name, next_sym->name);
} else if (stack->expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
- prop->filename, prop->lineno,
+ fprintf(stderr, "\tsymbol %s %s value contains %s\n",
sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
+ prop_get_type_name(type),
+ next_sym->name);
} else {
- fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
- prop->filename, prop->lineno,
+ fprintf(stderr, "\tsymbol %s %s is visible depending on %s\n",
sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
+ prop_get_type_name(type),
+ next_sym->name);
}
}
@@ -1121,7 +1138,7 @@ static void sym_check_print_recursive(struct symbol *last_sym)
dep_stack_remove();
}
-static struct symbol *sym_check_expr_deps(struct expr *e)
+static struct symbol *sym_check_expr_deps(const struct expr *e)
{
struct symbol *sym;
@@ -1182,8 +1199,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
stack.expr = NULL;
for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->type == P_CHOICE || prop->type == P_SELECT ||
- prop->type == P_IMPLY)
+ if (prop->type == P_SELECT || prop->type == P_IMPLY)
continue;
stack.prop = prop;
sym2 = sym_check_expr_deps(prop->visible.expr);
@@ -1237,9 +1253,13 @@ out:
if (menu->sym)
menu->sym->flags &= ~SYMBOL_CHECK;
- if (sym2 && sym_is_choice_value(sym2) &&
- prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
- sym2 = choice;
+ if (sym2) {
+ struct menu *choice_menu2;
+
+ choice_menu2 = sym_get_choice_menu(sym2);
+ if (choice_menu2 == choice_menu)
+ sym2 = choice;
+ }
dep_stack_remove();
@@ -1248,8 +1268,8 @@ out:
struct symbol *sym_check_deps(struct symbol *sym)
{
+ struct menu *choice;
struct symbol *sym2;
- struct property *prop;
if (sym->flags & SYMBOL_CHECK) {
sym_check_print_recursive(sym);
@@ -1258,13 +1278,13 @@ struct symbol *sym_check_deps(struct symbol *sym)
if (sym->flags & SYMBOL_CHECKED)
return NULL;
- if (sym_is_choice_value(sym)) {
+ choice = sym_get_choice_menu(sym);
+ if (choice) {
struct dep_stack stack;
/* for choice groups start the check with main choice symbol */
dep_stack_insert(&stack, sym);
- prop = sym_get_choice_prop(sym);
- sym2 = sym_check_deps(prop_get_symbol(prop));
+ sym2 = sym_check_deps(choice->sym);
dep_stack_remove();
} else if (sym_is_choice(sym)) {
sym2 = sym_check_choice_deps(sym);
@@ -1277,10 +1297,9 @@ struct symbol *sym_check_deps(struct symbol *sym)
return sym2;
}
-struct symbol *prop_get_symbol(struct property *prop)
+struct symbol *prop_get_symbol(const struct property *prop)
{
- if (prop->expr && (prop->expr->type == E_SYMBOL ||
- prop->expr->type == E_LIST))
+ if (prop->expr && prop->expr->type == E_SYMBOL)
return prop->expr->left.sym;
return NULL;
}
@@ -1296,8 +1315,6 @@ const char *prop_get_type_name(enum prop_type type)
return "menu";
case P_DEFAULT:
return "default";
- case P_CHOICE:
- return "choice";
case P_SELECT:
return "select";
case P_IMPLY:
diff --git a/scripts/kconfig/tests/choice/Kconfig b/scripts/kconfig/tests/choice/Kconfig
index 8cdda40868a1..cd252579a623 100644
--- a/scripts/kconfig/tests/choice/Kconfig
+++ b/scripts/kconfig/tests/choice/Kconfig
@@ -1,10 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-config MODULES
- bool "Enable loadable module support"
- modules
- default y
-
choice
prompt "boolean choice"
default BOOL_CHOICE1
@@ -16,15 +11,3 @@ config BOOL_CHOICE1
bool "choice 1"
endchoice
-
-choice
- prompt "tristate choice"
- default TRI_CHOICE1
-
-config TRI_CHOICE0
- tristate "choice 0"
-
-config TRI_CHOICE1
- tristate "choice 1"
-
-endchoice
diff --git a/scripts/kconfig/tests/choice/__init__.py b/scripts/kconfig/tests/choice/__init__.py
index 05e162220085..0fc7bf9b5c78 100644
--- a/scripts/kconfig/tests/choice/__init__.py
+++ b/scripts/kconfig/tests/choice/__init__.py
@@ -1,11 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
"""
Basic choice tests.
-
-The handling of 'choice' is a bit complicated part in Kconfig.
-
-The behavior of 'y' choice is intuitive. If choice values are tristate,
-the choice can be 'm' where each value can be enabled independently.
"""
@@ -14,11 +9,6 @@ def test_oldask0(conf):
assert conf.stdout_contains('oldask0_expected_stdout')
-def test_oldask1(conf):
- assert conf.oldaskconfig('oldask1_config') == 0
- assert conf.stdout_contains('oldask1_expected_stdout')
-
-
def test_allyes(conf):
assert conf.allyesconfig() == 0
assert conf.config_contains('allyes_expected_config')
diff --git a/scripts/kconfig/tests/choice/alldef_expected_config b/scripts/kconfig/tests/choice/alldef_expected_config
index 7a754bf4be94..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/alldef_expected_config
+++ b/scripts/kconfig/tests/choice/alldef_expected_config
@@ -1,5 +1,2 @@
-CONFIG_MODULES=y
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-# CONFIG_TRI_CHOICE0 is not set
-# CONFIG_TRI_CHOICE1 is not set
diff --git a/scripts/kconfig/tests/choice/allmod_expected_config b/scripts/kconfig/tests/choice/allmod_expected_config
index d1f51651740c..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/allmod_expected_config
+++ b/scripts/kconfig/tests/choice/allmod_expected_config
@@ -1,5 +1,2 @@
-CONFIG_MODULES=y
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-CONFIG_TRI_CHOICE0=m
-CONFIG_TRI_CHOICE1=m
diff --git a/scripts/kconfig/tests/choice/allno_expected_config b/scripts/kconfig/tests/choice/allno_expected_config
index b88ee7a43136..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/allno_expected_config
+++ b/scripts/kconfig/tests/choice/allno_expected_config
@@ -1,5 +1,2 @@
-# CONFIG_MODULES is not set
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-# CONFIG_TRI_CHOICE0 is not set
-CONFIG_TRI_CHOICE1=y
diff --git a/scripts/kconfig/tests/choice/allyes_expected_config b/scripts/kconfig/tests/choice/allyes_expected_config
index 8a76c1816893..b359a2e6493e 100644
--- a/scripts/kconfig/tests/choice/allyes_expected_config
+++ b/scripts/kconfig/tests/choice/allyes_expected_config
@@ -1,5 +1,2 @@
-CONFIG_MODULES=y
# CONFIG_BOOL_CHOICE0 is not set
CONFIG_BOOL_CHOICE1=y
-# CONFIG_TRI_CHOICE0 is not set
-CONFIG_TRI_CHOICE1=y
diff --git a/scripts/kconfig/tests/choice/oldask0_expected_stdout b/scripts/kconfig/tests/choice/oldask0_expected_stdout
index d2257db46423..80ec34c61ebc 100644
--- a/scripts/kconfig/tests/choice/oldask0_expected_stdout
+++ b/scripts/kconfig/tests/choice/oldask0_expected_stdout
@@ -1,8 +1,4 @@
-Enable loadable module support (MODULES) [Y/n/?] (NEW)
boolean choice
1. choice 0 (BOOL_CHOICE0) (NEW)
> 2. choice 1 (BOOL_CHOICE1) (NEW)
choice[1-2?]:
-tristate choice [M/y/?] (NEW)
- choice 0 (TRI_CHOICE0) [N/m/?] (NEW)
- choice 1 (TRI_CHOICE1) [N/m/?] (NEW)
diff --git a/scripts/kconfig/tests/choice/oldask1_config b/scripts/kconfig/tests/choice/oldask1_config
deleted file mode 100644
index 0f417856c81c..000000000000
--- a/scripts/kconfig/tests/choice/oldask1_config
+++ /dev/null
@@ -1 +0,0 @@
-# CONFIG_MODULES is not set
diff --git a/scripts/kconfig/tests/choice/oldask1_expected_stdout b/scripts/kconfig/tests/choice/oldask1_expected_stdout
deleted file mode 100644
index ffa20ad7f38e..000000000000
--- a/scripts/kconfig/tests/choice/oldask1_expected_stdout
+++ /dev/null
@@ -1,9 +0,0 @@
-Enable loadable module support (MODULES) [N/y/?]
-boolean choice
- 1. choice 0 (BOOL_CHOICE0) (NEW)
-> 2. choice 1 (BOOL_CHOICE1) (NEW)
-choice[1-2?]:
-tristate choice
- 1. choice 0 (TRI_CHOICE0) (NEW)
-> 2. choice 1 (TRI_CHOICE1) (NEW)
-choice[1-2?]:
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig b/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
deleted file mode 100644
index bd970cec07d6..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-config MODULES
- def_bool y
- modules
-
-config DEP
- tristate
- default m
-
-choice
- prompt "Tristate Choice"
-
-config CHOICE0
- tristate "Choice 0"
-
-config CHOICE1
- tristate "Choice 1"
- depends on DEP
-
-endchoice
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py b/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
deleted file mode 100644
index 075b4e08696e..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-"""
-Hide tristate choice values with mod dependency in y choice.
-
-If tristate choice values depend on symbols set to 'm', they should be
-hidden when the choice containing them is changed from 'm' to 'y'
-(i.e. exclusive choice).
-
-Related Linux commit: fa64e5f6a35efd5e77d639125d973077ca506074
-"""
-
-
-def test(conf):
- assert conf.oldaskconfig('config', 'y') == 0
- assert conf.config_contains('expected_config')
- assert conf.stdout_contains('expected_stdout')
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/config b/scripts/kconfig/tests/choice_value_with_m_dep/config
deleted file mode 100644
index 3a126b7a2546..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/config
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG_CHOICE0=m
-CONFIG_CHOICE1=m
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/expected_config b/scripts/kconfig/tests/choice_value_with_m_dep/expected_config
deleted file mode 100644
index 4d07b449540e..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/expected_config
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_MODULES=y
-CONFIG_DEP=m
-CONFIG_CHOICE0=y
diff --git a/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout b/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout
deleted file mode 100644
index 2b50ab65c86a..000000000000
--- a/scripts/kconfig/tests/choice_value_with_m_dep/expected_stdout
+++ /dev/null
@@ -1,4 +0,0 @@
-Tristate Choice [M/y/?] y
-Tristate Choice
-> 1. Choice 0 (CHOICE0)
-choice[1]: 1
diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
index 05d4ced70320..fc2e860af082 100644
--- a/scripts/kconfig/tests/err_recursive_dep/expected_stderr
+++ b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
@@ -1,38 +1,38 @@
-Kconfig:5:error: recursive dependency detected!
-Kconfig:5: symbol A depends on A
+error: recursive dependency detected!
+ symbol A depends on A
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:11:error: recursive dependency detected!
-Kconfig:11: symbol B is selected by B
+error: recursive dependency detected!
+ symbol B is selected by B
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:17:error: recursive dependency detected!
-Kconfig:17: symbol C1 depends on C2
-Kconfig:21: symbol C2 depends on C1
+error: recursive dependency detected!
+ symbol C1 depends on C2
+ symbol C2 depends on C1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:27:error: recursive dependency detected!
-Kconfig:27: symbol D1 depends on D2
-Kconfig:32: symbol D2 is selected by D1
+error: recursive dependency detected!
+ symbol D1 depends on D2
+ symbol D2 is selected by D1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:37:error: recursive dependency detected!
-Kconfig:37: symbol E1 depends on E2
-Kconfig:42: symbol E2 is implied by E1
+error: recursive dependency detected!
+ symbol E1 depends on E2
+ symbol E2 is implied by E1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:49:error: recursive dependency detected!
-Kconfig:49: symbol F1 default value contains F2
-Kconfig:51: symbol F2 depends on F1
+error: recursive dependency detected!
+ symbol F1 default value contains F2
+ symbol F2 depends on F1
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
-Kconfig:60:error: recursive dependency detected!
-Kconfig:60: symbol G depends on G
+error: recursive dependency detected!
+ symbol G depends on G
For a resolution refer to Documentation/kbuild/kconfig-language.rst
subsection "Kconfig recursive dependency limitations"
diff --git a/scripts/kconfig/tests/inter_choice/Kconfig b/scripts/kconfig/tests/inter_choice/Kconfig
deleted file mode 100644
index 26c25f68695b..000000000000
--- a/scripts/kconfig/tests/inter_choice/Kconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-config MODULES
- def_bool y
- modules
-
-choice
- prompt "Choice"
-
-config CHOICE_VAL0
- tristate "Choice 0"
-
-config CHOIVE_VAL1
- tristate "Choice 1"
-
-endchoice
-
-choice
- prompt "Another choice"
- depends on CHOICE_VAL0
-
-config DUMMY
- bool "dummy"
-
-endchoice
diff --git a/scripts/kconfig/tests/inter_choice/__init__.py b/scripts/kconfig/tests/inter_choice/__init__.py
deleted file mode 100644
index ffea6b1148a6..000000000000
--- a/scripts/kconfig/tests/inter_choice/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-"""
-Do not affect user-assigned choice value by another choice.
-
-Handling of state flags for choices is complecated. In old days,
-the defconfig result of a choice could be affected by another choice
-if those choices interact by 'depends on', 'select', etc.
-
-Related Linux commit: fbe98bb9ed3dae23e320c6b113e35f129538d14a
-"""
-
-
-def test(conf):
- assert conf.defconfig('defconfig') == 0
- assert conf.config_contains('expected_config')
diff --git a/scripts/kconfig/tests/inter_choice/defconfig b/scripts/kconfig/tests/inter_choice/defconfig
deleted file mode 100644
index 162c4148e2a5..000000000000
--- a/scripts/kconfig/tests/inter_choice/defconfig
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_CHOICE_VAL0=y
diff --git a/scripts/kconfig/tests/inter_choice/expected_config b/scripts/kconfig/tests/inter_choice/expected_config
deleted file mode 100644
index 5dceefb054e3..000000000000
--- a/scripts/kconfig/tests/inter_choice/expected_config
+++ /dev/null
@@ -1,4 +0,0 @@
-CONFIG_MODULES=y
-CONFIG_CHOICE_VAL0=y
-# CONFIG_CHOIVE_VAL1 is not set
-CONFIG_DUMMY=y
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 439c131b424e..696ff477671e 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -8,7 +8,7 @@
#include <stdlib.h>
#include <string.h>
-#include "hashtable.h"
+#include <hashtable.h>
#include "lkc.h"
unsigned int strhash(const char *s)
@@ -98,7 +98,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
}
/* Retrieve value of growable string */
-char *str_get(struct gstr *gs)
+char *str_get(const struct gstr *gs)
{
return gs->s;
}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 518c70b8db50..f7b2503cdba9 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -45,7 +45,6 @@ info()
# Link of vmlinux
# ${1} - output file
-# ${2}, ${3}, ... - optional extra .o files
vmlinux_link()
{
local output=${1}
@@ -90,7 +89,7 @@ vmlinux_link()
ldflags="${ldflags} ${wl}--script=${objtree}/${KBUILD_LDS}"
# The kallsyms linking does not need debug symbols included.
- if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
+ if [ -n "${strip_debug}" ] ; then
ldflags="${ldflags} ${wl}--strip-debug"
fi
@@ -101,15 +100,15 @@ vmlinux_link()
${ld} ${ldflags} -o ${output} \
${wl}--whole-archive ${objs} ${wl}--no-whole-archive \
${wl}--start-group ${libs} ${wl}--end-group \
- $@ ${ldlibs}
+ ${kallsymso} ${btf_vmlinux_bin_o} ${ldlibs}
}
# generate .BTF typeinfo from DWARF debuginfo
# ${1} - vmlinux image
-# ${2} - file to dump raw BTF data into
gen_btf()
{
local pahole_ver
+ local btf_data=${1}.btf.o
if ! [ -x "$(command -v ${PAHOLE})" ]; then
echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
@@ -122,18 +121,16 @@ gen_btf()
return 1
fi
- vmlinux_link ${1}
-
- info "BTF" ${2}
+ info BTF "${btf_data}"
LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1}
- # Create ${2} which contains just .BTF section but no symbols. Add
+ # Create ${btf_data} which contains just .BTF section but no symbols. Add
# SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
# deletes all symbols including __start_BTF and __stop_BTF, which will
# be redefined in the linker script. Add 2>/dev/null to suppress GNU
# objcopy warnings: "empty loadable segment detected at ..."
${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \
- --strip-all ${1} ${2} 2>/dev/null
+ --strip-all ${1} "${btf_data}" 2>/dev/null
# Change e_type to ET_REL so that it can be used to link final vmlinux.
# GNU ld 2.35+ and lld do not allow an ET_EXEC input.
if is_enabled CONFIG_CPU_BIG_ENDIAN; then
@@ -141,10 +138,12 @@ gen_btf()
else
et_rel='\1\0'
fi
- printf "${et_rel}" | dd of=${2} conv=notrunc bs=1 seek=16 status=none
+ printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none
+
+ btf_vmlinux_bin_o=${btf_data}
}
-# Create ${2} .S file with all symbols from the ${1} object file
+# Create ${2}.o file with all symbols from the ${1} object file
kallsyms()
{
local kallsymopt;
@@ -157,35 +156,27 @@ kallsyms()
kallsymopt="${kallsymopt} --absolute-percpu"
fi
- if is_enabled CONFIG_KALLSYMS_BASE_RELATIVE; then
- kallsymopt="${kallsymopt} --base-relative"
- fi
-
if is_enabled CONFIG_LTO_CLANG; then
kallsymopt="${kallsymopt} --lto-clang"
fi
- info KSYMS ${2}
- scripts/kallsyms ${kallsymopt} ${1} > ${2}
+ info KSYMS "${2}.S"
+ scripts/kallsyms ${kallsymopt} "${1}" > "${2}.S"
+
+ info AS "${2}.o"
+ ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \
+ ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} -c -o "${2}.o" "${2}.S"
+
+ kallsymso=${2}.o
}
-# Perform one step in kallsyms generation, including temporary linking of
-# vmlinux.
-kallsyms_step()
+# Perform kallsyms for the given temporary vmlinux.
+sysmap_and_kallsyms()
{
- kallsymso_prev=${kallsymso}
- kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1}
- kallsymso=${kallsyms_vmlinux}.o
- kallsyms_S=${kallsyms_vmlinux}.S
-
- vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
- mksysmap ${kallsyms_vmlinux} ${kallsyms_vmlinux}.syms
- kallsyms ${kallsyms_vmlinux}.syms ${kallsyms_S}
+ mksysmap "${1}" "${1}.syms"
+ kallsyms "${1}.syms" "${1}.kallsyms"
- info AS ${kallsymso}
- ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \
- ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
- -c -o ${kallsymso} ${kallsyms_S}
+ kallsyms_sysmap=${1}.syms
}
# Create map file with all symbols from ${1}
@@ -223,26 +214,40 @@ fi
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init init/version-timestamp.o
-btf_vmlinux_bin_o=""
+btf_vmlinux_bin_o=
+kallsymso=
+strip_debug=
+
+if is_enabled CONFIG_KALLSYMS; then
+ kallsyms /dev/null .tmp_vmlinux0.kallsyms
+fi
+
+if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DEBUG_INFO_BTF; then
+
+ # The kallsyms linking does not need debug symbols, but the BTF does.
+ if ! is_enabled CONFIG_DEBUG_INFO_BTF; then
+ strip_debug=1
+ fi
+
+ vmlinux_link .tmp_vmlinux1
+fi
+
if is_enabled CONFIG_DEBUG_INFO_BTF; then
- btf_vmlinux_bin_o=.btf.vmlinux.bin.o
- if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then
+ if ! gen_btf .tmp_vmlinux1; then
echo >&2 "Failed to generate BTF for vmlinux"
echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF"
exit 1
fi
fi
-kallsymso=""
-kallsymso_prev=""
-kallsyms_vmlinux=""
if is_enabled CONFIG_KALLSYMS; then
# kallsyms support
# Generate section listing all symbols and add it into vmlinux
- # It's a three step process:
+ # It's a four step process:
+ # 0) Generate a dummy __kallsyms with empty symbol list.
# 1) Link .tmp_vmlinux.kallsyms1 so it has all symbols and sections,
- # but __kallsyms is empty.
+ # with a dummy __kallsyms.
# Running kallsyms on that gives us .tmp_kallsyms1.o with
# the right size
# 2) Link .tmp_vmlinux.kallsyms2 so it now has a __kallsyms section of
@@ -261,19 +266,25 @@ if is_enabled CONFIG_KALLSYMS; then
# a) Verify that the System.map from vmlinux matches the map from
# ${kallsymso}.
- kallsyms_step 1
- kallsyms_step 2
+ # The kallsyms linking does not need debug symbols included.
+ strip_debug=1
- # step 3
- size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
+ sysmap_and_kallsyms .tmp_vmlinux1
+ size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
+
+ vmlinux_link .tmp_vmlinux2
+ sysmap_and_kallsyms .tmp_vmlinux2
size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
- kallsyms_step 3
+ vmlinux_link .tmp_vmlinux3
+ sysmap_and_kallsyms .tmp_vmlinux3
fi
fi
-vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
+strip_debug=
+
+vmlinux_link vmlinux
# fill in BTF IDs
if is_enabled CONFIG_DEBUG_INFO_BTF && is_enabled CONFIG_BPF; then
@@ -293,7 +304,7 @@ fi
# step a (see comment above)
if is_enabled CONFIG_KALLSYMS; then
- if ! cmp -s System.map ${kallsyms_vmlinux}.syms; then
+ if ! cmp -s System.map "${kallsyms_sysmap}"; then
echo >&2 Inconsistent kallsyms data
echo >&2 'Try "make KALLSYMS_EXTRA_PASS=1" as a workaround'
exit 1
diff --git a/scripts/make_fit.py b/scripts/make_fit.py
index 263147df80a4..4a1bb2f55861 100755
--- a/scripts/make_fit.py
+++ b/scripts/make_fit.py
@@ -22,6 +22,11 @@ the entire FIT.
Use -c to compress the data, using bzip2, gzip, lz4, lzma, lzo and
zstd algorithms.
+Use -D to decompose "composite" DTBs into their base components and
+deduplicate the resulting base DTBs and DTB overlays. This requires the
+DTBs to be sourced from the kernel build directory, as the implementation
+looks at the .cmd files produced by the kernel build.
+
The resulting FIT can be booted by bootloaders which support FIT, such
as U-Boot, Linuxboot, Tianocore, etc.
@@ -64,6 +69,8 @@ def parse_args():
help='Specifies the architecture')
parser.add_argument('-c', '--compress', type=str, default='none',
help='Specifies the compression')
+ parser.add_argument('-D', '--decompose-dtbs', action='store_true',
+ help='Decompose composite DTBs into base DTB and overlays')
parser.add_argument('-E', '--external', action='store_true',
help='Convert the FIT to use external data')
parser.add_argument('-n', '--name', type=str, required=True,
@@ -140,12 +147,12 @@ def finish_fit(fsw, entries):
fsw.end_node()
seq = 0
with fsw.add_node('configurations'):
- for model, compat in entries:
+ for model, compat, files in entries:
seq += 1
with fsw.add_node(f'conf-{seq}'):
fsw.property('compatible', bytes(compat))
fsw.property_string('description', model)
- fsw.property_string('fdt', f'fdt-{seq}')
+ fsw.property('fdt', bytes(''.join(f'fdt-{x}\x00' for x in files), "ascii"))
fsw.property_string('kernel', 'kernel')
fsw.end_node()
@@ -193,21 +200,9 @@ def output_dtb(fsw, seq, fname, arch, compress):
fname (str): Filename containing the DTB
arch: FIT architecture, e.g. 'arm64'
compress (str): Compressed algorithm, e.g. 'gzip'
-
- Returns:
- tuple:
- str: Model name
- bytes: Compatible stringlist
"""
with fsw.add_node(f'fdt-{seq}'):
- # Get the compatible / model information
- with open(fname, 'rb') as inf:
- data = inf.read()
- fdt = libfdt.FdtRo(data)
- model = fdt.getprop(0, 'model').as_str()
- compat = fdt.getprop(0, 'compatible')
-
- fsw.property_string('description', model)
+ fsw.property_string('description', os.path.basename(fname))
fsw.property_string('type', 'flat_dt')
fsw.property_string('arch', arch)
fsw.property_string('compression', compress)
@@ -215,9 +210,45 @@ def output_dtb(fsw, seq, fname, arch, compress):
with open(fname, 'rb') as inf:
compressed = compress_data(inf, compress)
fsw.property('data', compressed)
- return model, compat
+def process_dtb(fname, args):
+ """Process an input DTB, decomposing it if requested and is possible
+
+ Args:
+ fname (str): Filename containing the DTB
+ args (Namespace): Program arguments
+ Returns:
+ tuple:
+ str: Model name string
+ str: Root compatible string
+ files: list of filenames corresponding to the DTB
+ """
+ # Get the compatible / model information
+ with open(fname, 'rb') as inf:
+ data = inf.read()
+ fdt = libfdt.FdtRo(data)
+ model = fdt.getprop(0, 'model').as_str()
+ compat = fdt.getprop(0, 'compatible')
+
+ if args.decompose_dtbs:
+ # Check if the DTB needs to be decomposed
+ path, basename = os.path.split(fname)
+ cmd_fname = os.path.join(path, f'.{basename}.cmd')
+ with open(cmd_fname, 'r', encoding='ascii') as inf:
+ cmd = inf.read()
+
+ if 'scripts/dtc/fdtoverlay' in cmd:
+ # This depends on the structure of the composite DTB command
+ files = cmd.split()
+ files = files[files.index('-i') + 1:]
+ else:
+ files = [fname]
+ else:
+ files = [fname]
+
+ return (model, compat, files)
+
def build_fit(args):
"""Build the FIT from the provided files and arguments
@@ -235,6 +266,7 @@ def build_fit(args):
fsw = libfdt.FdtSw()
setup_fit(fsw, args.name)
entries = []
+ fdts = {}
# Handle the kernel
with open(args.kernel, 'rb') as inf:
@@ -243,12 +275,22 @@ def build_fit(args):
write_kernel(fsw, comp_data, args)
for fname in args.dtbs:
- # Ignore overlay (.dtbo) files
- if os.path.splitext(fname)[1] == '.dtb':
- seq += 1
- size += os.path.getsize(fname)
- model, compat = output_dtb(fsw, seq, fname, args.arch, args.compress)
- entries.append([model, compat])
+ # Ignore non-DTB (*.dtb) files
+ if os.path.splitext(fname)[1] != '.dtb':
+ continue
+
+ (model, compat, files) = process_dtb(fname, args)
+
+ for fn in files:
+ if fn not in fdts:
+ seq += 1
+ size += os.path.getsize(fn)
+ output_dtb(fsw, seq, fn, args.arch, args.compress)
+ fdts[fn] = seq
+
+ files_seq = [fdts[fn] for fn in files]
+
+ entries.append([model, compat, files_seq])
finish_fit(fsw, entries)
diff --git a/scripts/mod/list.h b/scripts/mod/list.h
deleted file mode 100644
index a924a6c4aa4d..000000000000
--- a/scripts/mod/list.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LIST_H
-#define LIST_H
-
-#include <stdbool.h>
-#include <stddef.h>
-
-/* Are two types/vars the same type (ignoring qualifiers)? */
-#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- void *__mptr = (void *)(ptr); \
- _Static_assert(__same_type(*(ptr), ((type *)0)->member) || \
- __same_type(*(ptr), void), \
- "pointer type mismatch in container_of()"); \
- ((type *)(__mptr - offsetof(type, member))); })
-
-#define LIST_POISON1 ((void *) 0x100)
-#define LIST_POISON2 ((void *) 0x122)
-
-/*
- * Circular doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-/**
- * INIT_LIST_HEAD - Initialize a list_head structure
- * @list: list_head structure to be initialized.
- *
- * Initializes the list_head to point to itself. If it is a list header,
- * the result is an empty list.
- */
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static inline void __list_del_entry(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del_entry(entry);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-
-/**
- * list_is_head - tests whether @list is the list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_head(const struct list_head *list, const struct list_head *head)
-{
- return list == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_head within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @ptr: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_head within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-/**
- * list_next_entry - get the next element in list
- * @pos: the type * to cursor
- * @member: the name of the list_head within the struct.
- */
-#define list_next_entry(pos, member) \
- list_entry((pos)->member.next, typeof(*(pos)), member)
-
-/**
- * list_entry_is_head - test if the entry points to the head of the list
- * @pos: the type * to cursor
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_entry_is_head(pos, head, member) \
- (&pos->member == (head))
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member); \
- !list_entry_is_head(pos, head, member); \
- pos = list_next_entry(pos, member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type. Safe against removal of list entry
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_first_entry(head, typeof(*pos), member), \
- n = list_next_entry(pos, member); \
- !list_entry_is_head(pos, head, member); \
- pos = n, n = list_next_entry(n, member))
-
-#endif /* LIST_H */
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 4b1edb257618..d16d0ace2775 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -20,6 +20,9 @@
#include <limits.h>
#include <stdbool.h>
#include <errno.h>
+
+#include <hashtable.h>
+#include <list.h>
#include "modpost.h"
#include "../../include/linux/license.h"
@@ -199,13 +202,8 @@ static struct module *new_module(const char *name, size_t namelen)
return mod;
}
-/* A hash of all exported symbols,
- * struct symbol is also used for lists of unresolved symbols */
-
-#define SYMBOL_HASH_SIZE 1024
-
struct symbol {
- struct symbol *next;
+ struct hlist_node hnode;/* link to hash table */
struct list_head list; /* link to module::exported_symbols or module::unresolved_symbols */
struct module *module;
char *namespace;
@@ -218,7 +216,7 @@ struct symbol {
char name[];
};
-static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
+static HASHTABLE_DEFINE(symbol_hashtable, 1U << 10);
/* This is based on the hash algorithm from gdbm, via tdb */
static inline unsigned int tdb_hash(const char *name)
@@ -250,11 +248,7 @@ static struct symbol *alloc_symbol(const char *name)
/* For the hash of exported symbols */
static void hash_add_symbol(struct symbol *sym)
{
- unsigned int hash;
-
- hash = tdb_hash(sym->name) % SYMBOL_HASH_SIZE;
- sym->next = symbolhash[hash];
- symbolhash[hash] = sym;
+ hash_add(symbol_hashtable, &sym->hnode, tdb_hash(sym->name));
}
static void sym_add_unresolved(const char *name, struct module *mod, bool weak)
@@ -275,7 +269,7 @@ static struct symbol *sym_find_with_module(const char *name, struct module *mod)
if (name[0] == '.')
name++;
- for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) {
+ hash_for_each_possible(symbol_hashtable, s, hnode, tdb_hash(name)) {
if (strcmp(s->name, name) == 0 && (!mod || s->module == mod))
return s;
}
@@ -954,17 +948,6 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
match(fromsym, PATTERNS("*_ops", "*_probe", "*_console")))
return 0;
- /*
- * symbols in data sections must not refer to .exit.*, but there are
- * quite a few offenders, so hide these unless for W=1 builds until
- * these are fixed.
- */
- if (!extra_warn &&
- match(fromsec, PATTERNS(DATA_SECTIONS)) &&
- match(tosec, PATTERNS(ALL_EXIT_SECTIONS)) &&
- match(fromsym, PATTERNS("*driver")))
- return 0;
-
/* Check for pattern 3 */
if (strstarts(fromsec, ".head.text") &&
match(tosec, PATTERNS(ALL_INIT_SECTIONS)))
@@ -1168,40 +1151,6 @@ static Elf_Addr addend_386_rel(uint32_t *location, unsigned int r_type)
return (Elf_Addr)(-1);
}
-#ifndef R_ARM_CALL
-#define R_ARM_CALL 28
-#endif
-#ifndef R_ARM_JUMP24
-#define R_ARM_JUMP24 29
-#endif
-
-#ifndef R_ARM_THM_CALL
-#define R_ARM_THM_CALL 10
-#endif
-#ifndef R_ARM_THM_JUMP24
-#define R_ARM_THM_JUMP24 30
-#endif
-
-#ifndef R_ARM_MOVW_ABS_NC
-#define R_ARM_MOVW_ABS_NC 43
-#endif
-
-#ifndef R_ARM_MOVT_ABS
-#define R_ARM_MOVT_ABS 44
-#endif
-
-#ifndef R_ARM_THM_MOVW_ABS_NC
-#define R_ARM_THM_MOVW_ABS_NC 47
-#endif
-
-#ifndef R_ARM_THM_MOVT_ABS
-#define R_ARM_THM_MOVT_ABS 48
-#endif
-
-#ifndef R_ARM_THM_JUMP19
-#define R_ARM_THM_JUMP19 51
-#endif
-
static int32_t sign_extend32(int32_t value, int index)
{
uint8_t shift = 31 - index;
@@ -1262,7 +1211,7 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
((lower & 0x07ff) << 1),
20);
return offset + sym->st_value + 4;
- case R_ARM_THM_CALL:
+ case R_ARM_THM_PC22:
case R_ARM_THM_JUMP24:
/*
* Encoding T4:
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index ee43c7950636..58197b34a3c8 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -13,7 +13,7 @@
#include <elf.h>
#include "../../include/linux/module_symbol.h"
-#include "list.h"
+#include <list_types.h>
#include "elfconfig.h"
/* On BSD-alike OSes elf.h defines these according to host's word size */
diff --git a/scripts/package/PKGBUILD b/scripts/package/PKGBUILD
new file mode 100644
index 000000000000..663ce300dd06
--- /dev/null
+++ b/scripts/package/PKGBUILD
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Maintainer: Thomas Weißschuh <linux@weissschuh.net>
+# Contributor: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
+
+pkgbase=${PACMAN_PKGBASE:-linux-upstream}
+pkgname=("${pkgbase}" "${pkgbase}-api-headers")
+if grep -q CONFIG_MODULES=y include/config/auto.conf; then
+ pkgname+=("${pkgbase}-headers")
+fi
+pkgver="${KERNELRELEASE//-/_}"
+# The PKGBUILD is evaluated multiple times.
+# Running scripts/build-version from here would introduce inconsistencies.
+pkgrel="${KBUILD_REVISION}"
+pkgdesc='Upstream Linux'
+url='https://www.kernel.org/'
+# Enable flexible cross-compilation
+arch=(${CARCH})
+license=(GPL-2.0-only)
+makedepends=(
+ bc
+ bison
+ cpio
+ flex
+ gettext
+ kmod
+ libelf
+ openssl
+ pahole
+ perl
+ python
+ rsync
+ tar
+)
+options=(!debug !strip !buildflags !makeflags)
+
+build() {
+ # MAKEFLAGS from makepkg.conf override the ones inherited from kbuild.
+ # Bypass this override with a custom variable.
+ export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
+ cd "${objtree}"
+
+ ${MAKE} KERNELRELEASE="${KERNELRELEASE}" KBUILD_BUILD_VERSION="${pkgrel}"
+}
+
+_package() {
+ pkgdesc="The ${pkgdesc} kernel and modules"
+
+ export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
+ cd "${objtree}"
+ local modulesdir="${pkgdir}/usr/${MODLIB}"
+
+ echo "Installing boot image..."
+ # systemd expects to find the kernel here to allow hibernation
+ # https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344
+ install -Dm644 "$(${MAKE} -s image_name)" "${modulesdir}/vmlinuz"
+
+ # Used by mkinitcpio to name the kernel
+ echo "${pkgbase}" > "${modulesdir}/pkgbase"
+
+ echo "Installing modules..."
+ ${MAKE} INSTALL_MOD_PATH="${pkgdir}/usr" INSTALL_MOD_STRIP=1 \
+ DEPMOD=true modules_install
+
+ if [ -d "${srctree}/arch/${SRCARCH}/boot/dts" ]; then
+ echo "Installing dtbs..."
+ ${MAKE} INSTALL_DTBS_PATH="${modulesdir}/dtb" dtbs_install
+ fi
+
+ # remove build link, will be part of -headers package
+ rm -f "${modulesdir}/build"
+}
+
+_package-headers() {
+ pkgdesc="Headers and scripts for building modules for the ${pkgdesc} kernel"
+
+ export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
+ cd "${objtree}"
+ local builddir="${pkgdir}/usr/${MODLIB}/build"
+
+ echo "Installing build files..."
+ "${srctree}/scripts/package/install-extmod-build" "${builddir}"
+
+ echo "Installing System.map and config..."
+ cp System.map "${builddir}/System.map"
+ cp .config "${builddir}/.config"
+
+ echo "Adding symlink..."
+ mkdir -p "${pkgdir}/usr/src"
+ ln -sr "${builddir}" "${pkgdir}/usr/src/${pkgbase}"
+}
+
+_package-api-headers() {
+ pkgdesc="Kernel headers sanitized for use in userspace"
+ provides=(linux-api-headers)
+ conflicts=(linux-api-headers)
+
+ export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
+ cd "${objtree}"
+
+ ${MAKE} headers_install INSTALL_HDR_PATH="${pkgdir}/usr"
+}
+
+for _p in "${pkgname[@]}"; do
+ eval "package_$_p() {
+ $(declare -f "_package${_p#$pkgbase}")
+ _package${_p#$pkgbase}
+ }"
+done
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index e797ad360f7a..c1757db6aa8a 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -10,7 +10,7 @@
# specified in KDEB_HOOKDIR) that will be called on package install and
# removal.
-set -e
+set -eu
is_enabled() {
grep -q "^$1=y" include/config/auto.conf
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index eb67787f8673..cc87a473c01f 100755
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -11,7 +11,7 @@
# Wichert Akkerman <wichert@wiggy.net>.
#
-set -e
+set -eu
#
# Some variables and settings used throughout the script
diff --git a/scripts/package/gen-diff-patch b/scripts/package/gen-diff-patch
index 8a98b7bb78a0..f272f7770ea3 100755
--- a/scripts/package/gen-diff-patch
+++ b/scripts/package/gen-diff-patch
@@ -1,6 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
+set -eu
+
diff_patch=$1
mkdir -p "$(dirname "${diff_patch}")"
diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
index 76e0765dfcd6..8cc9e13403ae 100755
--- a/scripts/package/install-extmod-build
+++ b/scripts/package/install-extmod-build
@@ -1,13 +1,10 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-only
-set -e
+set -eu
destdir=${1}
-test -n "${srctree}"
-test -n "${SRCARCH}"
-
is_enabled() {
grep -q "^$1=y" include/config/auto.conf
}
diff --git a/scripts/package/kernel.spec b/scripts/package/kernel.spec
index c52d517b9364..74355ff0e106 100644
--- a/scripts/package/kernel.spec
+++ b/scripts/package/kernel.spec
@@ -27,7 +27,7 @@ The Linux Kernel, the operating system core itself
%package headers
Summary: Header files for the Linux kernel for use by glibc
Group: Development/System
-Obsoletes: kernel-headers
+Obsoletes: kernel-headers < %{version}
Provides: kernel-headers = %{version}
%description headers
Kernel-headers includes the C header files that specify the interface
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian
index 070149c985fe..10637d403777 100755
--- a/scripts/package/mkdebian
+++ b/scripts/package/mkdebian
@@ -4,7 +4,7 @@
#
# Simple script to generate a debian/ directory for a Linux kernel.
-set -e
+set -eu
is_enabled() {
grep -q "^$1=y" include/config/auto.conf
@@ -19,7 +19,7 @@ if_enabled_echo() {
}
set_debarch() {
- if [ -n "$KBUILD_DEBARCH" ] ; then
+ if [ "${KBUILD_DEBARCH:+set}" ]; then
debarch="$KBUILD_DEBARCH"
return
fi
@@ -125,32 +125,34 @@ gen_source ()
rm -rf debian
mkdir debian
-email=${DEBEMAIL-$EMAIL}
-
-# use email string directly if it contains <email>
-if echo "${email}" | grep -q '<.*>'; then
- maintainer=${email}
+user=${KBUILD_BUILD_USER:-$(id -nu)}
+name=${DEBFULLNAME:-${user}}
+if [ "${DEBEMAIL:+set}" ]; then
+ email=${DEBEMAIL}
else
- # or construct the maintainer string
- user=${KBUILD_BUILD_USER-$(id -nu)}
- name=${DEBFULLNAME-${user}}
- if [ -z "${email}" ]; then
- buildhost=${KBUILD_BUILD_HOST-$(hostname -f 2>/dev/null || hostname)}
- email="${user}@${buildhost}"
- fi
- maintainer="${name} <${email}>"
+ buildhost=${KBUILD_BUILD_HOST:-$(hostname -f 2>/dev/null || hostname)}
+ email="${user}@${buildhost}"
fi
+maintainer="${name} <${email}>"
-if [ "$1" = --need-source ]; then
- gen_source
-fi
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --need-source)
+ gen_source
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
# Some variables and settings used throughout the script
version=$KERNELRELEASE
-if [ -n "$KDEB_PKGVERSION" ]; then
+if [ "${KDEB_PKGVERSION:+set}" ]; then
packageversion=$KDEB_PKGVERSION
else
- packageversion=$(${srctree}/scripts/setlocalversion --no-local ${srctree})-$($srctree/init/build-version)
+ packageversion=$(${srctree}/scripts/setlocalversion --no-local ${srctree})-$($srctree/scripts/build-version)
fi
sourcename=${KDEB_SOURCENAME:-linux-upstream}
@@ -164,7 +166,7 @@ debarch=
set_debarch
# Try to determine distribution
-if [ -n "$KDEB_CHANGELOG_DIST" ]; then
+if [ "${KDEB_CHANGELOG_DIST:+set}" ]; then
distribution=$KDEB_CHANGELOG_DIST
# In some cases lsb_release returns the codename as n/a, which breaks dpkg-parsechangelog
elif distribution=$(lsb_release -cs 2>/dev/null) && [ -n "$distribution" ] && [ "$distribution" != "n/a" ]; then
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index ce201bfa8377..ead54d67a024 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -9,6 +9,8 @@
# Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
#
+set -eu
+
output=$1
mkdir -p "$(dirname "${output}")"
@@ -24,7 +26,30 @@ fi
cat<<EOF
%define ARCH ${ARCH}
%define KERNELRELEASE ${KERNELRELEASE}
-%define pkg_release $("${srctree}/init/build-version")
+%define pkg_release $("${srctree}/scripts/build-version")
EOF
cat "${srctree}/scripts/package/kernel.spec"
+
+# collect the user's name and email address for the changelog entry
+if [ "$(command -v git)" ]; then
+ name=$(git config user.name) || true
+ email=$(git config user.email) || true
+fi
+
+if [ ! "${name:+set}" ]; then
+ name=${KBUILD_BUILD_USER:-$(id -nu)}
+fi
+
+if [ ! "${email:+set}" ]; then
+ buildhost=${KBUILD_BUILD_HOST:-$(hostname -f 2>/dev/null || hostname)}
+ builduser=${KBUILD_BUILD_USER:-$(id -nu)}
+ email="${builduser}@${buildhost}"
+fi
+
+cat << EOF
+
+%changelog
+* $(LC_ALL=C; date +'%a %b %d %Y') ${name} <${email}>
+- Custom built Linux kernel.
+EOF
diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files
index 385610fe3936..f38d26b78c2a 100755
--- a/scripts/remove-stale-files
+++ b/scripts/remove-stale-files
@@ -20,22 +20,4 @@ set -e
# yard. Stale files stay in this file for a while (for some release cycles?),
# then will be really dead and removed from the code base entirely.
-rm -f arch/powerpc/purgatory/kexec-purgatory.c
-rm -f arch/riscv/purgatory/kexec-purgatory.c
-rm -f arch/x86/purgatory/kexec-purgatory.c
-
-rm -f scripts/extract-cert
-
-rm -f scripts/kconfig/[gmnq]conf-cfg
-
-rm -f rust/target.json
-
-rm -f scripts/bin2c
-
-rm -f .scmversion
-
-rm -rf include/ksym
-
-find . -name '*.usyms' | xargs rm -f
-
rm -f *.spec