diff options
Diffstat (limited to 'scripts')
102 files changed, 2414 insertions, 1656 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/Kconfig.include b/scripts/Kconfig.include index 3ee8ecfb8c04..3500a3d62f0d 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -33,7 +33,8 @@ ld-option = $(success,$(LD) -v $(1))  # $(as-instr,<instr>)  # Return y if the assembler supports <instr>, n otherwise -as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -Wa$(comma)--fatal-warnings -c -x assembler-with-cpp -o /dev/null -) +as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) $(2) -Wa$(comma)--fatal-warnings -c -x assembler-with-cpp -o /dev/null -) +as-instr64 = $(as-instr,$(1),$(m64-flag))  # check if $(CC) and $(LD) exist  $(error-if,$(failure,command -v $(CC)),C compiler '$(CC)' not found) diff --git a/scripts/Makefile b/scripts/Makefile index fe56eeef09dd..dccef663ca82 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -12,7 +12,7 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE)	+= insert-sys-cert  hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS)		+= rustdoc_test_builder  hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS)		+= rustdoc_test_gen -ifdef CONFIG_X86_64 +ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),)  always-$(CONFIG_RUST)					+= target.json  filechk_rust_target = $< < include/config/auto.conf diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic deleted file mode 100644 index 1486abf34c7c..000000000000 --- a/scripts/Makefile.asm-generic +++ /dev/null @@ -1,58 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# include/asm-generic contains a lot of files that are used -# verbatim by several architectures. -# -# This Makefile reads the file arch/$(SRCARCH)/include/(uapi/)/asm/Kbuild -# and for each file listed in this file with generic-y creates -# a small wrapper file in arch/$(SRCARCH)/include/generated/(uapi/)/asm. - -PHONY := all -all: - -src := $(srctree)/$(subst /generated,,$(obj)) - -include $(srctree)/scripts/Kbuild.include --include $(kbuild-file) - -# $(generic)/Kbuild lists mandatory-y. Exclude um since it is a special case. -ifneq ($(SRCARCH),um) -include $(srctree)/$(generic)/Kbuild -endif - -redundant := $(filter $(mandatory-y) $(generated-y), $(generic-y)) -redundant += $(foreach f, $(generic-y), $(if $(wildcard $(src)/$(f)),$(f))) -redundant := $(sort $(redundant)) -$(if $(redundant),\ -	$(warning redundant generic-y found in $(src)/Kbuild: $(redundant))) - -# If arch does not implement mandatory headers, fallback to asm-generic ones. -mandatory-y := $(filter-out $(generated-y), $(mandatory-y)) -generic-y   += $(foreach f, $(mandatory-y), $(if $(wildcard $(src)/$(f)),,$(f))) - -generic-y   := $(addprefix $(obj)/, $(generic-y)) -generated-y := $(addprefix $(obj)/, $(generated-y)) - -# Remove stale wrappers when the corresponding files are removed from generic-y -old-headers := $(wildcard $(obj)/*.h) -unwanted    := $(filter-out $(generic-y) $(generated-y),$(old-headers)) - -quiet_cmd_wrap = WRAP    $@ -      cmd_wrap = echo "\#include <asm-generic/$*.h>" > $@ - -quiet_cmd_remove = REMOVE  $(unwanted) -      cmd_remove = rm -f $(unwanted) - -all: $(generic-y) -	$(if $(unwanted),$(call cmd,remove)) -	@: - -$(obj)/%.h: -	$(call cmd,wrap) - -# Create output directory. Skip it if at least one old header exists -# since we know the output directory already exists. -ifeq ($(old-headers),) -$(shell mkdir -p $(obj)) -endif - -.PHONY: $(PHONY) diff --git a/scripts/Makefile.asm-headers b/scripts/Makefile.asm-headers new file mode 100644 index 000000000000..8a4856e74180 --- /dev/null +++ b/scripts/Makefile.asm-headers @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: GPL-2.0 +# include/asm-generic contains a lot of files that are used +# verbatim by several architectures. +# +# This Makefile generates arch/$(SRCARCH)/include/generated/(uapi/)/asm +# headers from multiple sources: +#  - a small wrapper to include the corresponding asm-generic/*.h +#    is generated for each file listed as generic-y +#  - uapi/asm/unistd_*.h files listed as syscalls-y are generated from +#    syscall.tbl with the __NR_* macros +#  - Corresponding asm/syscall_table_*.h are generated from the same input + +PHONY := all +all: + +src := $(srctree)/$(subst /generated,,$(obj)) + +syscall_abis_32  += common,32 +syscall_abis_64  += common,64 +syscalltbl := $(srctree)/scripts/syscall.tbl +syshdr-args := --emit-nr + +# let architectures override $(syscall_abis_%) and $(syscalltbl) +-include $(srctree)/arch/$(SRCARCH)/kernel/Makefile.syscalls +include $(srctree)/scripts/Kbuild.include +-include $(kbuild-file) + +syshdr := $(srctree)/scripts/syscallhdr.sh +systbl := $(srctree)/scripts/syscalltbl.sh + +# $(generic)/Kbuild lists mandatory-y. Exclude um since it is a special case. +ifneq ($(SRCARCH),um) +include $(srctree)/$(generic)/Kbuild +endif + +redundant := $(filter $(mandatory-y) $(generated-y), $(generic-y)) +redundant += $(foreach f, $(generic-y), $(if $(wildcard $(src)/$(f)),$(f))) +redundant := $(sort $(redundant)) +$(if $(redundant),\ +	$(warning redundant generic-y found in $(src)/Kbuild: $(redundant))) + +# If arch does not implement mandatory headers, fallback to asm-generic ones. +mandatory-y := $(filter-out $(generated-y), $(mandatory-y)) +generic-y   += $(foreach f, $(mandatory-y), $(if $(wildcard $(src)/$(f)),,$(f))) + +generic-y   := $(addprefix $(obj)/, $(generic-y)) +syscall-y   := $(addprefix $(obj)/, $(syscall-y)) +generated-y := $(addprefix $(obj)/, $(generated-y)) + +# Remove stale wrappers when the corresponding files are removed from generic-y +old-headers := $(wildcard $(obj)/*.h) +unwanted    := $(filter-out $(generic-y) $(generated-y) $(syscall-y),$(old-headers)) + +quiet_cmd_wrap = WRAP    $@ +      cmd_wrap = echo "\#include <asm-generic/$*.h>" > $@ + +quiet_cmd_remove = REMOVE  $(unwanted) +      cmd_remove = rm -f $(unwanted) + +quiet_cmd_syshdr = SYSHDR  $@ +      cmd_syshdr = $(CONFIG_SHELL) $(syshdr) \ +		   $(if $(syshdr-args-$*),$(syshdr-args-$*),$(syshdr-args)) \ +		   $(if $(syscall_compat),--prefix "compat$*_") \ +		   --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \ +		   $< $@ + +quiet_cmd_systbl = SYSTBL  $@ +      cmd_systbl = $(CONFIG_SHELL) $(systbl) \ +		   $(if $(systbl-args-$*),$(systbl-args-$*),$(systbl-args)) \ +		   --abis $(subst $(space),$(comma),$(strip $(syscall_abis_$*))) \ +		   $< $@ + +all: $(generic-y) $(syscall-y) +	$(if $(unwanted),$(call cmd,remove)) +	@: + +$(obj)/%.h: $(srctree)/$(generic)/%.h +	$(call cmd,wrap) + +$(obj)/unistd_%.h: $(syscalltbl) $(syshdr) FORCE +	$(call if_changed,syshdr) + +$(obj)/unistd_compat_%.h: syscall_compat:=1 +$(obj)/unistd_compat_%.h: $(syscalltbl) $(syshdr) FORCE +	$(call if_changed,syshdr) + +$(obj)/syscall_table_%.h: $(syscalltbl) $(systbl) FORCE +	$(call if_changed,systbl) + +targets := $(syscall-y) + +# Create output directory. Skip it if at least one old header exists +# since we know the output directory already exists. +ifeq ($(old-headers),) +$(shell mkdir -p $(obj)) +endif + +PHONY += FORCE + +FORCE: + +existing-targets := $(wildcard $(sort $(targets))) + +-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + +.PHONY: $(PHONY) diff --git a/scripts/Makefile.btf b/scripts/Makefile.btf index 2d6e5ed9081e..b75f09f3f424 100644 --- a/scripts/Makefile.btf +++ b/scripts/Makefile.btf @@ -14,17 +14,20 @@ pahole-flags-$(call test-ge, $(pahole-ver), 121)	+= --btf_gen_floats  pahole-flags-$(call test-ge, $(pahole-ver), 122)	+= -j -ifeq ($(pahole-ver), 125) -pahole-flags-y	+= --skip_encoding_btf_inconsistent_proto --btf_gen_optimized -endif +pahole-flags-$(call test-ge, $(pahole-ver), 125)	+= --skip_encoding_btf_inconsistent_proto --btf_gen_optimized  else  # Switch to using --btf_features for v1.26 and later. -pahole-flags-$(call test-ge, $(pahole-ver), 126)  = -j --btf_features=encode_force,var,float,enum64,decl_tag,type_tag,optimized_func,consistent_func +pahole-flags-$(call test-ge, $(pahole-ver), 126)  = -j --btf_features=encode_force,var,float,enum64,decl_tag,type_tag,optimized_func,consistent_func,decl_tag_kfuncs + +ifneq ($(KBUILD_EXTMOD),) +module-pahole-flags-$(call test-ge, $(pahole-ver), 126) += --btf_features=distilled_base +endif  endif  pahole-flags-$(CONFIG_PAHOLE_HAS_LANG_EXCLUDE)		+= --lang_exclude=rust  export PAHOLE_FLAGS := $(pahole-flags-y) +export MODULE_PAHOLE_FLAGS := $(module-pahole-flags-y) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 9f06f6aaf7fc..fe3668dc4954 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -407,8 +407,19 @@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ;  		-d $(depfile).dtc.tmp $(dtc-tmp) ; \  	cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) +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 $(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  	$(call if_changed,fdtoverlay) @@ -421,7 +432,7 @@ DT_BINDING_DIR := Documentation/devicetree/bindings  DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.json  quiet_cmd_dtb =	DTC_CHK $@ -      cmd_dtb =	$(cmd_dtc) ; $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ || true +      cmd_dtb =	$(cmd_dtc) ; $(DT_CHECK_CMD) $@ || true  else  quiet_cmd_dtb = $(quiet_cmd_dtc)        cmd_dtb = $(cmd_dtc) @@ -522,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.modfinal b/scripts/Makefile.modfinal index 3bec9043e4f3..1fa98b5e952b 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -41,7 +41,7 @@ quiet_cmd_btf_ko = BTF [M] $@  	if [ ! -f vmlinux ]; then					\  		printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \  	else								\ -		LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) --btf_base vmlinux $@; \ +		LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base vmlinux $@; \  		$(RESOLVE_BTFIDS) -b vmlinux $@; 			\  	fi; 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/checkpatch.pl b/scripts/checkpatch.pl index 2b812210b412..39032224d504 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -28,6 +28,7 @@ my %verbose_messages = ();  my %verbose_emitted = ();  my $tree = 1;  my $chk_signoff = 1; +my $chk_fixes_tag = 1;  my $chk_patch = 1;  my $tst_only;  my $emacs = 0; @@ -88,6 +89,7 @@ Options:    -v, --verbose              verbose mode    --no-tree                  run without a kernel tree    --no-signoff               do not check for 'Signed-off-by' line +  --no-fixes-tag             do not check for 'Fixes:' tag    --patch                    treat FILE as patchfile (default)    --emacs                    emacs compile window format    --terse                    one line per report @@ -295,6 +297,7 @@ GetOptions(  	'v|verbose!'	=> \$verbose,  	'tree!'		=> \$tree,  	'signoff!'	=> \$chk_signoff, +	'fixes-tag!'	=> \$chk_fixes_tag,  	'patch!'	=> \$chk_patch,  	'emacs!'	=> \$emacs,  	'terse!'	=> \$terse, @@ -1257,6 +1260,7 @@ sub git_commit_info {  }  $chk_signoff = 0 if ($file); +$chk_fixes_tag = 0 if ($file);  my @rawlines = ();  my @lines = (); @@ -2636,6 +2640,9 @@ sub process {  	our $clean = 1;  	my $signoff = 0; +	my $fixes_tag = 0; +	my $is_revert = 0; +	my $needs_fixes_tag = "";  	my $author = '';  	my $authorsignoff = 0;  	my $author_sob = ''; @@ -3189,6 +3196,16 @@ sub process {  			}  		} +# These indicate a bug fix +		if (!$in_header_lines && !$is_patch && +			$line =~ /^This reverts commit/) { +			$is_revert = 1; +		} + +		if (!$in_header_lines && !$is_patch && +		    $line =~ /((?:(?:BUG: K.|UB)SAN: |Call Trace:|stable\@|syzkaller))/) { +			$needs_fixes_tag = $1; +		}  # Check Fixes: styles is correct  		if (!$in_header_lines && @@ -3201,6 +3218,7 @@ sub process {  			my $id_length = 1;  			my $id_case = 1;  			my $title_has_quotes = 0; +			$fixes_tag = 1;  			if ($line =~ /(\s*fixes:?)\s+([0-9a-f]{5,})\s+($balanced_parens)/i) {  				my $tag = $1; @@ -3858,7 +3876,7 @@ sub process {  			}  			if ($msg_type ne "" && -			    (show_type("LONG_LINE") || show_type($msg_type))) { +			    show_type("LONG_LINE") && show_type($msg_type)) {  				my $msg_level = \&WARN;  				$msg_level = \&CHK if ($file);  				&{$msg_level}($msg_type, @@ -7697,6 +7715,12 @@ sub process {  		ERROR("NOT_UNIFIED_DIFF",  		      "Does not appear to be a unified-diff format patch\n");  	} +	if ($is_patch && $has_commit_log && $chk_fixes_tag) { +		if ($needs_fixes_tag ne "" && !$is_revert && !$fixes_tag) { +			WARN("MISSING_FIXES_TAG", +				 "The commit message has '$needs_fixes_tag', perhaps it also needs a 'Fixes:' tag?\n"); +		} +	}  	if ($is_patch && $has_commit_log && $chk_signoff) {  		if ($signoff == 0) {  			ERROR("MISSING_SIGN_OFF", diff --git a/scripts/checktransupdate.py b/scripts/checktransupdate.py new file mode 100755 index 000000000000..5a0fc99e3f93 --- /dev/null +++ b/scripts/checktransupdate.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +""" +This script helps track the translation status of the documentation +in different locales, e.g., zh_CN. More specially, it uses `git log` +commit to find the latest english commit from the translation commit +(order by author date) and the latest english commits from HEAD. If +differences occur, report the file and commits that need to be updated. + +The usage is as follows: +- ./scripts/checktransupdate.py -l zh_CN +This will print all the files that need to be updated in the zh_CN locale. +- ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst +This will only print the status of the specified file. + +The output is something like: +Documentation/translations/zh_CN/dev-tools/testing-overview.rst (1 commits) +commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs") +""" + +import os +from argparse import ArgumentParser, BooleanOptionalAction +from datetime import datetime + +flag_p_c = False +flag_p_uf = False +flag_debug = False + + +def dprint(*args, **kwargs): +    if flag_debug: +        print("[DEBUG] ", end="") +        print(*args, **kwargs) + + +def get_origin_path(file_path): +    paths = file_path.split("/") +    tidx = paths.index("translations") +    opaths = paths[:tidx] +    opaths += paths[tidx + 2 :] +    return "/".join(opaths) + + +def get_latest_commit_from(file_path, commit): +    command = "git log --pretty=format:%H%n%aD%n%cD%n%n%B {} -1 -- {}".format( +        commit, file_path +    ) +    dprint(command) +    pipe = os.popen(command) +    result = pipe.read() +    result = result.split("\n") +    if len(result) <= 1: +        return None + +    dprint("Result: {}".format(result[0])) + +    return { +        "hash": result[0], +        "author_date": datetime.strptime(result[1], "%a, %d %b %Y %H:%M:%S %z"), +        "commit_date": datetime.strptime(result[2], "%a, %d %b %Y %H:%M:%S %z"), +        "message": result[4:], +    } + + +def get_origin_from_trans(origin_path, t_from_head): +    o_from_t = get_latest_commit_from(origin_path, t_from_head["hash"]) +    while o_from_t is not None and o_from_t["author_date"] > t_from_head["author_date"]: +        o_from_t = get_latest_commit_from(origin_path, o_from_t["hash"] + "^") +    if o_from_t is not None: +        dprint("tracked origin commit id: {}".format(o_from_t["hash"])) +    return o_from_t + + +def get_commits_count_between(opath, commit1, commit2): +    command = "git log --pretty=format:%H {}...{} -- {}".format(commit1, commit2, opath) +    dprint(command) +    pipe = os.popen(command) +    result = pipe.read().split("\n") +    # filter out empty lines +    result = list(filter(lambda x: x != "", result)) +    return result + + +def pretty_output(commit): +    command = "git log --pretty='format:%h (\"%s\")' -1 {}".format(commit) +    dprint(command) +    pipe = os.popen(command) +    return pipe.read() + + +def check_per_file(file_path): +    opath = get_origin_path(file_path) + +    if not os.path.isfile(opath): +        dprint("Error: Cannot find the origin path for {}".format(file_path)) +        return + +    o_from_head = get_latest_commit_from(opath, "HEAD") +    t_from_head = get_latest_commit_from(file_path, "HEAD") + +    if o_from_head is None or t_from_head is None: +        print("Error: Cannot find the latest commit for {}".format(file_path)) +        return + +    o_from_t = get_origin_from_trans(opath, t_from_head) + +    if o_from_t is None: +        print("Error: Cannot find the latest origin commit for {}".format(file_path)) +        return + +    if o_from_head["hash"] == o_from_t["hash"]: +        if flag_p_uf: +            print("No update needed for {}".format(file_path)) +        return +    else: +        print("{}".format(file_path), end="\t") +        commits = get_commits_count_between( +            opath, o_from_t["hash"], o_from_head["hash"] +        ) +        print("({} commits)".format(len(commits))) +        if flag_p_c: +            for commit in commits: +                msg = pretty_output(commit) +                if "Merge tag" not in msg: +                    print("commit", msg) + + +def main(): +    script_path = os.path.dirname(os.path.abspath(__file__)) +    linux_path = os.path.join(script_path, "..") + +    parser = ArgumentParser(description="Check the translation update") +    parser.add_argument( +        "-l", +        "--locale", +        help="Locale to check when files are not specified", +    ) +    parser.add_argument( +        "--print-commits", +        action=BooleanOptionalAction, +        default=True, +        help="Print commits between the origin and the translation", +    ) + +    parser.add_argument( +        "--print-updated-files", +        action=BooleanOptionalAction, +        default=False, +        help="Print files that do no need to be updated", +    ) + +    parser.add_argument( +        "--debug", +        action=BooleanOptionalAction, +        help="Print debug information", +        default=False, +    ) + +    parser.add_argument( +        "files", nargs="*", help="Files to check, if not specified, check all files" +    ) +    args = parser.parse_args() + +    global flag_p_c, flag_p_uf, flag_debug +    flag_p_c = args.print_commits +    flag_p_uf = args.print_updated_files +    flag_debug = args.debug + +    # get files related to linux path +    files = args.files +    if len(files) == 0: +        if args.locale is not None: +            files = ( +                os.popen( +                    "find {}/Documentation/translations/{} -type f".format( +                        linux_path, args.locale +                    ) +                ) +                .read() +                .split("\n") +            ) +        else: +            files = ( +                os.popen( +                    "find {}/Documentation/translations -type f".format(linux_path) +                ) +                .read() +                .split("\n") +            ) + +    files = list(filter(lambda x: x != "", files)) +    files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files)) + +    # cd to linux root directory +    os.chdir(linux_path) + +    for file in files: +        check_per_file(file) + + +if __name__ == "__main__": +    main() diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch index 52e5bfb61fd0..014b3bfe3237 100644 --- a/scripts/const_structs.checkpatch +++ b/scripts/const_structs.checkpatch @@ -64,7 +64,17 @@ platform_suspend_ops  proc_ops  proto_ops  pwm_ops +reg_default +reg_field +reg_sequence  regmap_access_table +regmap_bus +regmap_config +regmap_irq +regmap_irq_chip +regmap_irq_sub_irq_map +regmap_range +regmap_range_cfg  regulator_ops  reset_control_ops  rpc_pipe_ops @@ -79,6 +89,7 @@ snd_rawmidi_ops  snd_soc_component_driver  snd_soc_dai_ops  snd_soc_ops +snd_soc_tplg_ops  soc_pcmcia_socket_ops  stacktrace_ops  sysfs_ops diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index fa5be6f57b00..a0f50a5b4f7c 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -30,6 +30,7 @@ fi  READELF=${UTIL_PREFIX}readelf${UTIL_SUFFIX}  ADDR2LINE=${UTIL_PREFIX}addr2line${UTIL_SUFFIX} +NM=${UTIL_PREFIX}nm${UTIL_SUFFIX}  if [[ $1 == "-r" ]] ; then  	vmlinux="" @@ -158,7 +159,7 @@ parse_symbol() {  	if [[ $aarray_support == true && "${cache[$module,$name]+isset}" == "isset" ]]; then  		local base_addr=${cache[$module,$name]}  	else -		local base_addr=$(nm "$objfile" 2>/dev/null | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}') +		local base_addr=$(${NM} "$objfile" 2>/dev/null | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}')  		if [[ $base_addr == "" ]] ; then  			# address not found  			return @@ -282,6 +283,9 @@ handle_line() {  	if [[ ${words[$last]} =~ \[([^]]+)\] ]]; then  		module=${words[$last]} +		# some traces format is "(%pS)", which like "(foo+0x0/0x1 [bar])" +		# so $module may like "[bar])". Strip the right parenthesis firstly +		module=${module%\)}  		module=${module#\[}  		module=${module%\]}  		modbuildid=${module#* } diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index 9f31d2607182..10fb63894369 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -31,7 +31,7 @@ typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node  struct check {  	const char *name;  	check_fn fn; -	void *data; +	const void *data;  	bool warn, error;  	enum checkstatus status;  	bool inprogress; @@ -114,6 +114,7 @@ static inline void  PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,  	}  	fputs(str, stderr); +	free(str);  }  #define FAIL(c, dti, node, ...)						\ @@ -207,7 +208,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,  			    struct node *node)  {  	struct property *prop; -	char *propname = c->data; +	const char *propname = c->data;  	prop = get_property(node, propname);  	if (!prop) @@ -226,7 +227,7 @@ static void check_is_string_list(struct check *c, struct dt_info *dti,  {  	int rem, l;  	struct property *prop; -	char *propname = c->data; +	const char *propname = c->data;  	char *str;  	prop = get_property(node, propname); @@ -254,7 +255,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,  			  struct node *node)  {  	struct property *prop; -	char *propname = c->data; +	const char *propname = c->data;  	prop = get_property(node, propname);  	if (!prop) @@ -1078,10 +1079,11 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node  		/* Ignore I2C_OWN_SLAVE_ADDRESS */  		reg &= ~I2C_OWN_SLAVE_ADDRESS; -		if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)) -			FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", +		if (reg & I2C_TEN_BIT_ADDRESS) { +			if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff) +				FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",  				  reg); -		else if (reg > 0x7f) +		} else if (reg > 0x7f)  			FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property",  				  reg);  	} @@ -1108,7 +1110,7 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no  		for_each_child(node, child) {  			struct property *prop;  			for_each_property(child, prop) { -				if (strprefixeq(prop->name, 4, "spi-")) { +				if (strstarts(prop->name, "spi-")) {  					node->bus = &spi_bus;  					break;  				} @@ -1180,7 +1182,7 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,  		/* skip over 0x for next test */  		unitname += 2;  	} -	if (unitname[0] == '0' && isxdigit(unitname[1])) +	if (unitname[0] == '0' && isxdigit((unsigned char)unitname[1]))  		FAIL(c, dti, node, "unit name should not have leading 0s");  }  WARNING(unit_address_format, check_unit_address_format, NULL, @@ -1222,7 +1224,7 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d  	if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)  		return; -	if (get_property(node, "ranges") || !node->children) +	if (get_property(node, "ranges") || get_property(node, "dma-ranges") || !node->children)  		return;  	for_each_child(node, child) { @@ -1232,7 +1234,7 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d  	}  	if (!has_reg) -		FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property"); +		FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" property");  }  WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); @@ -1465,7 +1467,7 @@ static void check_provider_cells_property(struct check *c,  					  struct dt_info *dti,  				          struct node *node)  { -	struct provider *provider = c->data; +	const struct provider *provider = c->data;  	struct property *prop;  	prop = get_property(node, provider->prop_name); @@ -1673,6 +1675,10 @@ static void check_interrupt_map(struct check *c,  			parent_cellsize += propval_cell(cellprop);  		cell += 1 + parent_cellsize; +		if (cell > map_cells) +			FAIL_PROP(c, dti, node, irq_map_prop, +				"property size (%d) mismatch, expected %zu", +				irq_map_prop->val.len, cell * sizeof(cell_t));  	}  }  WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider); @@ -1765,6 +1771,11 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,  		      get_property(child, "remote-endpoint")))  			continue; +                /* The root node cannot be a port */ +		if (!node->parent) { +			FAIL(c, dti, node, "root node contains endpoint node '%s', potentially misplaced remote-endpoint property", child->name); +			continue; +		}  		node->bus = &graph_port_bus;  		/* The parent of 'port' nodes can be either 'ports' or a device */ @@ -1778,31 +1789,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,  }  WARNING(graph_nodes, check_graph_nodes, NULL); -static void check_graph_child_address(struct check *c, struct dt_info *dti, -				      struct node *node) -{ -	int cnt = 0; -	struct node *child; - -	if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) -		return; - -	for_each_child(node, child) { -		struct property *prop = get_property(child, "reg"); - -		/* No error if we have any non-zero unit address */ -		if (prop && propval_cell(prop) != 0) -			return; - -		cnt++; -	} - -	if (cnt == 1 && node->addr_cells != -1) -		FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", -		     node->children->name); -} -WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes); -  static void check_graph_reg(struct check *c, struct dt_info *dti,  			    struct node *node)  { @@ -1893,6 +1879,31 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,  }  WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes); +static void check_graph_child_address(struct check *c, struct dt_info *dti, +				      struct node *node) +{ +	int cnt = 0; +	struct node *child; + +	if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) +		return; + +	for_each_child(node, child) { +		struct property *prop = get_property(child, "reg"); + +		/* No error if we have any non-zero unit address */ +                if (prop && propval_cell(prop) != 0 ) +			return; + +		cnt++; +	} + +	if (cnt == 1 && node->addr_cells != -1) +		FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", +		     node->children->name); +} +WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes, &graph_port, &graph_endpoint); +  static struct check *check_table[] = {  	&duplicate_node_names, &duplicate_property_names,  	&node_name_chars, &node_name_format, &property_name_chars, diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index bff1337ec266..4d5eece52624 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -284,14 +284,17 @@ propdef:  	  DT_PROPNODENAME '=' propdata ';'  		{  			$$ = build_property($1, $3, &@$); +			free($1);  		}  	| DT_PROPNODENAME ';'  		{  			$$ = build_property($1, empty_data, &@$); +			free($1);  		}  	| DT_DEL_PROP DT_PROPNODENAME ';'  		{  			$$ = build_property_delete($2); +			free($2);  		}  	| DT_LABEL propdef  		{ @@ -570,10 +573,12 @@ subnode:  	  DT_PROPNODENAME nodedef  		{  			$$ = name_node($2, $1); +			free($1);  		}  	| DT_DEL_NODE DT_PROPNODENAME ';'  		{  			$$ = name_node(build_node_delete(&@$), $2); +			free($2);  		}  	| DT_OMIT_NO_REF subnode  		{ diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index bc786c543b7e..0655c2e2c362 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -47,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)  /* Usage related data. */  static const char usage_synopsis[] = "dtc [options] <input file>"; -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv";  static struct option const usage_long_opts[] = {  	{"quiet",            no_argument, NULL, 'q'},  	{"in-format",         a_argument, NULL, 'I'}, @@ -67,6 +67,7 @@ static struct option const usage_long_opts[] = {  	{"warning",           a_argument, NULL, 'W'},  	{"error",             a_argument, NULL, 'E'},  	{"symbols",	     no_argument, NULL, '@'}, +	{"local-fixups",     no_argument, NULL, 'L'},  	{"auto-alias",       no_argument, NULL, 'A'},  	{"annotate",         no_argument, NULL, 'T'},  	{"help",             no_argument, NULL, 'h'}, @@ -104,6 +105,7 @@ static const char * const usage_opts_help[] = {  	"\n\tEnable/disable warnings (prefix with \"no-\")",  	"\n\tEnable/disable errors (prefix with \"no-\")",  	"\n\tEnable generation of symbols", +	"\n\tPossibly generates a __local_fixups__ and a __fixups__ node at the root node",  	"\n\tEnable auto-alias of labels",  	"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",  	"\n\tPrint this help and exit", @@ -252,6 +254,11 @@ int main(int argc, char *argv[])  		case '@':  			generate_symbols = 1;  			break; + +		case 'L': +			generate_fixups = 1; +			break; +  		case 'A':  			auto_label_aliases = 1;  			break; diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index 0a1f54991026..4c4aaca1fc41 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -260,16 +260,16 @@ struct node {  void add_label(struct label **labels, char *label);  void delete_labels(struct label **labels); -struct property *build_property(char *name, struct data val, +struct property *build_property(const char *name, struct data val,  				struct srcpos *srcpos); -struct property *build_property_delete(char *name); +struct property *build_property_delete(const char *name);  struct property *chain_property(struct property *first, struct property *list);  struct property *reverse_properties(struct property *first);  struct node *build_node(struct property *proplist, struct node *children,  			struct srcpos *srcpos);  struct node *build_node_delete(struct srcpos *srcpos); -struct node *name_node(struct node *node, char *name); +struct node *name_node(struct node *node, const char *name);  struct node *omit_node_if_unused(struct node *node);  struct node *reference_node(struct node *node);  struct node *chain_node(struct node *first, struct node *list); @@ -336,9 +336,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags,  			      struct reserve_info *reservelist,  			      struct node *tree, uint32_t boot_cpuid_phys);  void sort_tree(struct dt_info *dti); -void generate_label_tree(struct dt_info *dti, char *name, bool allocph); -void generate_fixups_tree(struct dt_info *dti, char *name); -void generate_local_fixups_tree(struct dt_info *dti, char *name); +void generate_label_tree(struct dt_info *dti, const char *name, bool allocph); +void generate_fixups_tree(struct dt_info *dti, const char *name); +void generate_local_fixups_tree(struct dt_info *dti, const char *name);  /* Checks */ diff --git a/scripts/dtc/fdtoverlay.c b/scripts/dtc/fdtoverlay.c index 5350af65679f..4eba0460f240 100644 --- a/scripts/dtc/fdtoverlay.c +++ b/scripts/dtc/fdtoverlay.c @@ -23,9 +23,7 @@  /* Usage related data. */  static const char usage_synopsis[] =  	"apply a number of overlays to a base blob\n" -	"	fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n" -	"\n" -	USAGE_TYPE_MSG; +	"	fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";  static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;  static struct option const usage_long_opts[] = {  	{"input",            required_argument, NULL, 'i'}, @@ -50,7 +48,7 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,  	int ret;  	/* -	 * We take a copies first, because a a failed apply can trash +	 * We take a copies first, because a failed apply can trash  	 * both the base blob and the overlay  	 */  	tmpo = xmalloc(fdt_totalsize(overlay)); diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index 95e43d32c3e6..1bcd8089c5b9 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -604,11 +604,11 @@ static void flat_realign(struct inbuf *inb, int align)  		die("Premature end of data parsing flat device tree\n");  } -static char *flat_read_string(struct inbuf *inb) +static const char *flat_read_string(struct inbuf *inb)  {  	int len = 0;  	const char *p = inb->ptr; -	char *str; +	const char *str;  	do {  		if (p >= inb->limit) @@ -616,7 +616,7 @@ static char *flat_read_string(struct inbuf *inb)  		len++;  	} while ((*p++) != '\0'); -	str = xstrdup(inb->ptr); +	str = inb->ptr;  	inb->ptr += len; @@ -711,7 +711,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)  } -static char *nodename_from_path(const char *ppath, const char *cpath) +static const char *nodename_from_path(const char *ppath, const char *cpath)  {  	int plen; @@ -725,7 +725,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)  	if (!streq(ppath, "/"))  		plen++; -	return xstrdup(cpath + plen); +	return cpath + plen;  }  static struct node *unflatten_tree(struct inbuf *dtbuf, @@ -733,7 +733,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,  				   const char *parent_flatname, int flags)  {  	struct node *node; -	char *flatname; +	const char *flatname;  	uint32_t val;  	node = build_node(NULL, NULL, NULL); @@ -741,9 +741,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,  	flatname = flat_read_string(dtbuf);  	if (flags & FTF_FULLPATH) -		node->name = nodename_from_path(parent_flatname, flatname); +		node->name = xstrdup(nodename_from_path(parent_flatname, +							flatname));  	else -		node->name = flatname; +		node->name = xstrdup(flatname);  	do {  		struct property *prop; @@ -785,10 +786,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,  		}  	} while (val != FDT_END_NODE); -	if (node->name != flatname) { -		free(flatname); -	} -  	return node;  } diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c index 5e59594ab301..0f9a534bacdb 100644 --- a/scripts/dtc/fstree.c +++ b/scripts/dtc/fstree.c @@ -43,7 +43,7 @@ static struct node *read_fstree(const char *dirname)  					"WARNING: Cannot open %s: %s\n",  					tmpname, strerror(errno));  			} else { -				prop = build_property(xstrdup(de->d_name), +				prop = build_property(de->d_name,  						      data_copy_file(pfile,  								     st.st_size),  						      NULL); diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index 5c0c3981b89d..28b667ffc490 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -101,26 +101,22 @@ int fdt_overlay_target_offset(const void *fdt, const void *fdto,  static int overlay_phandle_add_offset(void *fdt, int node,  				      const char *name, uint32_t delta)  { -	const fdt32_t *val; -	uint32_t adj_val; +	fdt32_t *valp, val;  	int len; -	val = fdt_getprop(fdt, node, name, &len); -	if (!val) +	valp = fdt_getprop_w(fdt, node, name, &len); +	if (!valp)  		return len; -	if (len != sizeof(*val)) +	if (len != sizeof(val))  		return -FDT_ERR_BADPHANDLE; -	adj_val = fdt32_to_cpu(*val); -	if ((adj_val + delta) < adj_val) -		return -FDT_ERR_NOPHANDLES; - -	adj_val += delta; -	if (adj_val == (uint32_t)-1) +	val = fdt32_ld(valp); +	if (val + delta < val || val + delta == (uint32_t)-1)  		return -FDT_ERR_NOPHANDLES; -	return fdt_setprop_inplace_u32(fdt, node, name, adj_val); +	fdt32_st(valp, val + delta); +	return 0;  }  /** @@ -213,8 +209,8 @@ static int overlay_update_local_node_references(void *fdto,  	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {  		const fdt32_t *fixup_val; -		const char *tree_val;  		const char *name; +		char *tree_val;  		int fixup_len;  		int tree_len;  		int i; @@ -228,7 +224,7 @@ static int overlay_update_local_node_references(void *fdto,  			return -FDT_ERR_BADOVERLAY;  		fixup_len /= sizeof(uint32_t); -		tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); +		tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);  		if (!tree_val) {  			if (tree_len == -FDT_ERR_NOTFOUND)  				return -FDT_ERR_BADOVERLAY; @@ -237,33 +233,15 @@ static int overlay_update_local_node_references(void *fdto,  		}  		for (i = 0; i < fixup_len; i++) { -			fdt32_t adj_val; -			uint32_t poffset; +			fdt32_t *refp; -			poffset = fdt32_to_cpu(fixup_val[i]); +			refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));  			/* -			 * phandles to fixup can be unaligned. -			 * -			 * Use a memcpy for the architectures that do -			 * not support unaligned accesses. +			 * phandles to fixup can be unaligned, so use +			 * fdt32_{ld,st}() to read/write them.  			 */ -			memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); - -			adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); - -			ret = fdt_setprop_inplace_namelen_partial(fdto, -								  tree_node, -								  name, -								  strlen(name), -								  poffset, -								  &adj_val, -								  sizeof(adj_val)); -			if (ret == -FDT_ERR_NOSPACE) -				return -FDT_ERR_BADOVERLAY; - -			if (ret) -				return ret; +			fdt32_st(refp, fdt32_ld(refp) + delta);  		}  	} @@ -337,7 +315,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)   * @name: Name of the property holding the phandle reference in the overlay   * @name_len: number of name characters to consider   * @poffset: Offset within the overlay property where the phandle is stored - * @label: Label of the node referenced by the phandle + * @phandle: Phandle referencing the node   *   * overlay_fixup_one_phandle() resolves an overlay phandle pointing to   * a node in the base device tree. @@ -354,30 +332,14 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,  				     int symbols_off,  				     const char *path, uint32_t path_len,  				     const char *name, uint32_t name_len, -				     int poffset, const char *label) +				     int poffset, uint32_t phandle)  { -	const char *symbol_path; -	uint32_t phandle;  	fdt32_t phandle_prop; -	int symbol_off, fixup_off; -	int prop_len; +	int fixup_off;  	if (symbols_off < 0)  		return symbols_off; -	symbol_path = fdt_getprop(fdt, symbols_off, label, -				  &prop_len); -	if (!symbol_path) -		return prop_len; - -	symbol_off = fdt_path_offset(fdt, symbol_path); -	if (symbol_off < 0) -		return symbol_off; - -	phandle = fdt_get_phandle(fdt, symbol_off); -	if (!phandle) -		return -FDT_ERR_NOTFOUND; -  	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);  	if (fixup_off == -FDT_ERR_NOTFOUND)  		return -FDT_ERR_BADOVERLAY; @@ -416,6 +378,10 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,  	const char *value;  	const char *label;  	int len; +	const char *symbol_path; +	int prop_len; +	int symbol_off; +	uint32_t phandle;  	value = fdt_getprop_by_offset(fdto, property,  				      &label, &len); @@ -426,6 +392,18 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,  		return len;  	} +	symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len); +	if (!symbol_path) +		return prop_len; +	 +	symbol_off = fdt_path_offset(fdt, symbol_path); +	if (symbol_off < 0) +		return symbol_off; +	 +	phandle = fdt_get_phandle(fdt, symbol_off); +	if (!phandle) +		return -FDT_ERR_NOTFOUND; +  	do {  		const char *path, *name, *fixup_end;  		const char *fixup_str = value; @@ -467,7 +445,7 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,  		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,  						path, path_len, name, name_len, -						poffset, label); +						poffset, phandle);  		if (ret)  			return ret;  	} while (len > 0); @@ -521,6 +499,255 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)  }  /** + * overlay_adjust_local_conflicting_phandle: Changes a phandle value + * @fdto: Device tree overlay + * @node: The node the phandle is set for + * @fdt_phandle: The new value for the phandle + * + * returns: + *      0 on success + *      Negative error code on failure + */ +static int overlay_adjust_local_conflicting_phandle(void *fdto, int node, +						    uint32_t fdt_phandle) +{ +	const fdt32_t *php; +	int len, ret; + +	php = fdt_getprop(fdto, node, "phandle", &len); +	if (php && len == sizeof(*php)) { +		ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle); +		if (ret) +			return ret; +	} + +	php = fdt_getprop(fdto, node, "linux,phandle", &len); +	if (php && len == sizeof(*php)) { +		ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle); +		if (ret) +			return ret; +	} + +	return 0; +} + +/** + * overlay_update_node_conflicting_references - Recursively replace phandle values + * @fdto: Device tree overlay blob + * @tree_node: Node to recurse into + * @fixup_node: Node offset of the matching local fixups node + * @fdt_phandle: Value to replace phandles with + * @fdto_phandle: Value to be replaced + * + * Replaces all phandles with value @fdto_phandle by @fdt_phandle. + * + * returns: + *      0 on success + *      Negative error code on failure + */ +static int overlay_update_node_conflicting_references(void *fdto, int tree_node, +						      int fixup_node, +						      uint32_t fdt_phandle, +						      uint32_t fdto_phandle) +{ +	int fixup_prop; +	int fixup_child; +	int ret; + +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { +		const fdt32_t *fixup_val; +		const char *name; +		char *tree_val; +		int fixup_len; +		int tree_len; +		int i; + +		fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, +						  &name, &fixup_len); +		if (!fixup_val) +			return fixup_len; + +		if (fixup_len % sizeof(uint32_t)) +			return -FDT_ERR_BADOVERLAY; +		fixup_len /= sizeof(uint32_t); + +		tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len); +		if (!tree_val) { +			if (tree_len == -FDT_ERR_NOTFOUND) +				return -FDT_ERR_BADOVERLAY; + +			return tree_len; +		} + +		for (i = 0; i < fixup_len; i++) { +			fdt32_t *refp; +			uint32_t valp; + +			refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i)); +			valp = fdt32_ld(refp); + +			if (valp == fdto_phandle) +				fdt32_st(refp, fdt_phandle); +		} +	} + +	fdt_for_each_subnode(fixup_child, fdto, fixup_node) { +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL); +		int tree_child; + +		tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name); + +		if (tree_child == -FDT_ERR_NOTFOUND) +			return -FDT_ERR_BADOVERLAY; +		if (tree_child < 0) +			return tree_child; + +		ret = overlay_update_node_conflicting_references(fdto, tree_child, +								 fixup_child, +								 fdt_phandle, +								 fdto_phandle); +		if (ret) +			return ret; +	} + +	return 0; +} + +/** + * overlay_update_local_conflicting_references - Recursively replace phandle values + * @fdto: Device tree overlay blob + * @fdt_phandle: Value to replace phandles with + * @fdto_phandle: Value to be replaced + * + * Replaces all phandles with value @fdto_phandle by @fdt_phandle. + * + * returns: + *      0 on success + *      Negative error code on failure + */ +static int overlay_update_local_conflicting_references(void *fdto, +						       uint32_t fdt_phandle, +						       uint32_t fdto_phandle) +{ +	int fixups; + +	fixups = fdt_path_offset(fdto, "/__local_fixups__"); +	if (fixups == -FDT_ERR_NOTFOUND) +		return 0; +	if (fixups < 0) +		return fixups; + +	return overlay_update_node_conflicting_references(fdto, 0, fixups, +							  fdt_phandle, +							  fdto_phandle); +} + +/** + * overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite + * @fdt: Base Device tree blob + * @fdtnode: Node in fdt that is checked for an overwrite + * @fdto: Device tree overlay blob + * @fdtonode: Node in fdto matching @fdtnode + * + * returns: + *      0 on success + *      Negative error code on failure + */ +static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode, +						  void *fdto, int fdtonode) +{ +	uint32_t fdt_phandle, fdto_phandle; +	int fdtochild; + +	fdt_phandle = fdt_get_phandle(fdt, fdtnode); +	fdto_phandle = fdt_get_phandle(fdto, fdtonode); + +	if (fdt_phandle && fdto_phandle) { +		int ret; + +		ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode, +							       fdt_phandle); +		if (ret) +			return ret; + +		ret = overlay_update_local_conflicting_references(fdto, +								  fdt_phandle, +								  fdto_phandle); +		if (ret) +			return ret; +	} + +	fdt_for_each_subnode(fdtochild, fdto, fdtonode) { +		const char *name = fdt_get_name(fdto, fdtochild, NULL); +		int fdtchild; +		int ret; + +		fdtchild = fdt_subnode_offset(fdt, fdtnode, name); +		if (fdtchild == -FDT_ERR_NOTFOUND) +			/* +			 * no further overwrites possible here as this node is +			 * new +			 */ +			continue; + +		ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild, +							     fdto, fdtochild); +		if (ret) +			return ret; +	} + +	return 0; +} + +/** + * overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * Checks recursively if applying fdto overwrites phandle values in the base + * dtb. When such a phandle is found, the fdto is changed to use the fdt's + * phandle value to not break references in the base. + * + * returns: + *      0 on success + *      Negative error code on failure + */ +static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto) +{ +	int fragment; + +	fdt_for_each_subnode(fragment, fdto, 0) { +		int overlay; +		int target; +		int ret; + +		overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); +		if (overlay == -FDT_ERR_NOTFOUND) +			continue; + +		if (overlay < 0) +			return overlay; + +		target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL); +		if (target == -FDT_ERR_NOTFOUND) +			/* +			 * The subtree doesn't exist in the base, so nothing +			 * will be overwritten. +			 */ +			continue; +		else if (target < 0) +			return target; + +		ret = overlay_prevent_phandle_overwrite_node(fdt, target, +							     fdto, overlay); +		if (ret) +			return ret; +	} + +	return 0; +} + +/**   * overlay_apply_node - Merges a node into the base device tree   * @fdt: Base Device Tree blob   * @target: Node offset in the base device tree to apply the fragment to @@ -824,18 +1051,26 @@ int fdt_overlay_apply(void *fdt, void *fdto)  	if (ret)  		goto err; +	/* Increase all phandles in the fdto by delta */  	ret = overlay_adjust_local_phandles(fdto, delta);  	if (ret)  		goto err; +	/* Adapt the phandle values in fdto to the above increase */  	ret = overlay_update_local_references(fdto, delta);  	if (ret)  		goto err; +	/* Update fdto's phandles using symbols from fdt */  	ret = overlay_fixup_phandles(fdt, fdto);  	if (ret)  		goto err; +	/* Don't overwrite phandles in fdt */ +	ret = overlay_prevent_phandle_overwrite(fdt, fdto); +	if (ret) +		goto err; +  	ret = overlay_merge(fdt, fdto);  	if (ret)  		goto err; diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 9f6c551a22c2..b78c4e48f1cb 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -255,6 +255,9 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)  	FDT_RO_PROBE(fdt); +	if (!can_assume(VALID_INPUT) && namelen <= 0) +		return -FDT_ERR_BADPATH; +  	/* see if we have an alias */  	if (*path != '/') {  		const char *q = memchr(path, '/', end - p); @@ -522,16 +525,31 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)  	return fdt32_ld_(php);  } +static const void *fdt_path_getprop_namelen(const void *fdt, const char *path, +					    const char *propname, int propnamelen, +					    int *lenp) +{ +	int offset = fdt_path_offset(fdt, path); + +	if (offset < 0) +		return NULL; + +	return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp); +} +  const char *fdt_get_alias_namelen(const void *fdt,  				  const char *name, int namelen)  { -	int aliasoffset; +	int len; +	const char *alias; -	aliasoffset = fdt_path_offset(fdt, "/aliases"); -	if (aliasoffset < 0) +	alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len); + +	if (!can_assume(VALID_DTB) && +	    !(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))  		return NULL; -	return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +	return alias;  }  const char *fdt_get_alias(const void *fdt, const char *name) @@ -539,6 +557,17 @@ const char *fdt_get_alias(const void *fdt, const char *name)  	return fdt_get_alias_namelen(fdt, name, strlen(name));  } +const char *fdt_get_symbol_namelen(const void *fdt, +				   const char *name, int namelen) +{ +	return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL); +} + +const char *fdt_get_symbol(const void *fdt, const char *name) +{ +	return fdt_get_symbol_namelen(fdt, name, strlen(name)); +} +  int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)  {  	int pdepth = 0, p = 0; diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index 77ccff19911e..2d409d8e829b 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -524,10 +524,35 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);   * level matching the given component, differentiated only by unit   * address).   * + * If the path is not absolute (i.e. does not begin with '/'), the + * first component is treated as an alias.  That is, the property by + * that name is looked up in the /aliases node, and the value of that + * property used in place of that first component. + * + * For example, for this small fragment + * + * / { + *     aliases { + *         i2c2 = &foo; // RHS compiles to "/soc@0/i2c@30a40000/eeprom@52" + *     }; + *     soc@0 { + *         foo: i2c@30a40000 { + *             bar: eeprom@52 { + *             }; + *         }; + *     }; + * }; + * + * these would be equivalent: + * + *   /soc@0/i2c@30a40000/eeprom@52 + *   i2c2/eeprom@52 + *   * returns:   *	structure block offset of the node with the requested path (>=0), on   *		success - *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + *	-FDT_ERR_BADPATH, given path does not begin with '/' and the first + *		component is not a valid alias   *	-FDT_ERR_NOTFOUND, if the requested node does not exist   *      -FDT_ERR_BADMAGIC,   *	-FDT_ERR_BADVERSION, @@ -870,6 +895,42 @@ const char *fdt_get_alias_namelen(const void *fdt,  const char *fdt_get_alias(const void *fdt, const char *name);  /** + * fdt_get_symbol_namelen - get symbol based on substring + * @fdt: pointer to the device tree blob + * @name: name of the symbol to look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_symbol(), but only examine the first @namelen + * characters of @name for matching the symbol name. + * + * Return: a pointer to the expansion of the symbol named @name, if it exists, + *	   NULL otherwise + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_symbol_namelen(const void *fdt, +				   const char *name, int namelen); +#endif + +/** + * fdt_get_symbol - retrieve the path referenced by a given symbol + * @fdt: pointer to the device tree blob + * @name: name of the symbol to look up + * + * fdt_get_symbol() retrieves the value of a given symbol.  That is, + * the value of the property named @name in the node + * /__symbols__. Such a node exists only for a device tree blob that + * has been compiled with the -@ dtc option. Each property corresponds + * to a label appearing in the device tree source, with the name of + * the property being the label and the value being the full path of + * the node it is attached to. + * + * returns: + *	a pointer to the expansion of the symbol named 'name', if it exists + *	NULL, if the given symbol or the /__symbols__ node does not exist + */ +const char *fdt_get_symbol(const void *fdt, const char *name); + +/**   * fdt_get_path - determine the full path of a node   * @fdt: pointer to the device tree blob   * @nodeoffset: offset of the node whose path to find @@ -1450,7 +1511,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);   * fdt_create_with_flags() begins the process of creating a new fdt with   * the sequential write interface.   * - * fdt creation process must end with fdt_finished() to produce a valid fdt. + * fdt creation process must end with fdt_finish() to produce a valid fdt.   *   * returns:   *	0, on success @@ -1968,7 +2029,7 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,   * address and size) to the value of the named property in the given   * node, or creates a new property with that value if it does not   * already exist. - * If "name" is not specified, a default "reg" is used. + *   * Cell sizes are determined by parent's #address-cells and #size-cells.   *   * This function may insert data into the blob, and will therefore diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index f46a098d5ada..49f723002f85 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -36,27 +36,27 @@ void delete_labels(struct label **labels)  		label->deleted = 1;  } -struct property *build_property(char *name, struct data val, +struct property *build_property(const char *name, struct data val,  				struct srcpos *srcpos)  {  	struct property *new = xmalloc(sizeof(*new));  	memset(new, 0, sizeof(*new)); -	new->name = name; +	new->name = xstrdup(name);  	new->val = val;  	new->srcpos = srcpos_copy(srcpos);  	return new;  } -struct property *build_property_delete(char *name) +struct property *build_property_delete(const char *name)  {  	struct property *new = xmalloc(sizeof(*new));  	memset(new, 0, sizeof(*new)); -	new->name = name; +	new->name = xstrdup(name);  	new->deleted = 1;  	return new; @@ -116,11 +116,11 @@ struct node *build_node_delete(struct srcpos *srcpos)  	return new;  } -struct node *name_node(struct node *node, char *name) +struct node *name_node(struct node *node, const char *name)  {  	assert(node->name == NULL); -	node->name = name; +	node->name = xstrdup(name);  	return node;  } @@ -250,6 +250,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)  	name_node(new_node, "__overlay__");  	node = build_node(p, new_node, NULL);  	name_node(node, name); +	free(name);  	add_child(dt, node);  	return dt; @@ -440,7 +441,7 @@ cell_t propval_cell(struct property *prop)  cell_t propval_cell_n(struct property *prop, unsigned int n)  { -	assert(prop->val.len / sizeof(cell_t) >= n); +	assert(prop->val.len / sizeof(cell_t) > n);  	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));  } @@ -616,10 +617,25 @@ struct node *get_node_by_ref(struct node *tree, const char *ref)  	return target;  } +static void add_phandle_property(struct node *node, +				 const char *name, int format) +{ +	struct data d; + +	if (!(phandle_format & format)) +		return; +	if (get_property(node, name)) +		return; + +	d = data_add_marker(empty_data, TYPE_UINT32, NULL); +	d = data_append_cell(d, node->phandle); + +	add_property(node, build_property(name, d, NULL)); +} +  cell_t get_node_phandle(struct node *root, struct node *node)  {  	static cell_t phandle = 1; /* FIXME: ick, static local */ -	struct data d = empty_data;  	if (phandle_is_valid(node->phandle))  		return node->phandle; @@ -629,16 +645,8 @@ cell_t get_node_phandle(struct node *root, struct node *node)  	node->phandle = phandle; -	d = data_add_marker(d, TYPE_UINT32, NULL); -	d = data_append_cell(d, phandle); - -	if (!get_property(node, "linux,phandle") -	    && (phandle_format & PHANDLE_LEGACY)) -		add_property(node, build_property("linux,phandle", d, NULL)); - -	if (!get_property(node, "phandle") -	    && (phandle_format & PHANDLE_EPAPR)) -		add_property(node, build_property("phandle", d, NULL)); +	add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY); +	add_phandle_property(node, "phandle", PHANDLE_EPAPR);  	/* If the node *does* have a phandle property, we must  	 * be dealing with a self-referencing phandle, which will be @@ -808,18 +816,18 @@ void sort_tree(struct dt_info *dti)  }  /* utility helper to avoid code duplication */ -static struct node *build_and_name_child_node(struct node *parent, char *name) +static struct node *build_and_name_child_node(struct node *parent, const char *name)  {  	struct node *node;  	node = build_node(NULL, NULL, NULL); -	name_node(node, xstrdup(name)); +	name_node(node, name);  	add_child(parent, node);  	return node;  } -static struct node *build_root_node(struct node *dt, char *name) +static struct node *build_root_node(struct node *dt, const char *name)  {  	struct node *an; @@ -1040,7 +1048,7 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,  		generate_local_fixups_tree_internal(dti, lfn, c);  } -void generate_label_tree(struct dt_info *dti, char *name, bool allocph) +void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)  {  	if (!any_label_tree(dti, dti->dt))  		return; @@ -1048,7 +1056,7 @@ void generate_label_tree(struct dt_info *dti, char *name, bool allocph)  				     dti->dt, allocph);  } -void generate_fixups_tree(struct dt_info *dti, char *name) +void generate_fixups_tree(struct dt_info *dti, const char *name)  {  	if (!any_fixup_tree(dti, dti->dt))  		return; @@ -1056,7 +1064,7 @@ void generate_fixups_tree(struct dt_info *dti, char *name)  				      dti->dt);  } -void generate_local_fixups_tree(struct dt_info *dti, char *name) +void generate_local_fixups_tree(struct dt_info *dti, const char *name)  {  	if (!any_local_fixup_tree(dti, dti->dt))  		return; diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index 4fdb22a019bd..8e4d18a90b47 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c @@ -3,7 +3,9 @@   * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.   */ +#ifndef _GNU_SOURCE  #define _GNU_SOURCE +#endif  #include <stdio.h> @@ -311,8 +313,8 @@ srcpos_string(struct srcpos *pos)  static char *  srcpos_string_comment(struct srcpos *pos, bool first_line, int level)  { -	char *pos_str, *fname, *first, *rest; -	bool fresh_fname = false; +	char *pos_str, *fresh_fname = NULL, *first, *rest; +	const char *fname;  	if (!pos) {  		if (level > 1) { @@ -330,9 +332,9 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)  	else if (level > 1)  		fname = pos->file->name;  	else { -		fname = shorten_to_initial_path(pos->file->name); -		if (fname) -			fresh_fname = true; +		fresh_fname = shorten_to_initial_path(pos->file->name); +		if (fresh_fname) +			fname = fresh_fname;  		else  			fname = pos->file->name;  	} @@ -346,7 +348,7 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)  			  first_line ? pos->first_line : pos->last_line);  	if (fresh_fname) -		free(fname); +		free(fresh_fname);  	if (pos->next != NULL) {  		rest = srcpos_string_comment(pos->next, first_line, level); diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index 33fedee82d58..ae15839ba6a5 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -139,6 +139,28 @@ static const char *delim_end[] = {  	[TYPE_STRING] = "",  }; +static void add_string_markers(struct property *prop) +{ +	int l, len = prop->val.len; +	const char *p = prop->val.val; + +	for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1) { +		struct marker *m, **nextp; + +		m = xmalloc(sizeof(*m)); +		m->offset = l; +		m->type = TYPE_STRING; +		m->ref = NULL; +		m->next = NULL; + +		/* Find the end of the markerlist */ +		nextp = &prop->val.markers; +		while (*nextp) +			nextp = &((*nextp)->next); +		*nextp = m; +	} +} +  static enum markertype guess_value_type(struct property *prop)  {  	int len = prop->val.len; @@ -164,6 +186,8 @@ static enum markertype guess_value_type(struct property *prop)  	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))  	    && (nnotstringlbl == 0)) { +		if (nnul > 1) +			add_string_markers(prop);  		return TYPE_STRING;  	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {  		return TYPE_UINT32; @@ -241,6 +265,8 @@ static void write_propval(FILE *f, struct property *prop)  			} else {  				write_propval_int(f, p, chunk_len, 4);  			} +			if (data_len > chunk_len) +				fputc(' ', f);  			break;  		case TYPE_UINT64:  			write_propval_int(f, p, chunk_len, 8); diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index 9d38edee9736..b448cd79efd3 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -13,7 +13,9 @@   */  #ifdef __GNUC__ -#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +#ifdef __MINGW_PRINTF_FORMAT +#define PRINTF(i, j)	__attribute__((format (__MINGW_PRINTF_FORMAT, i, j))) +#elif __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)  #define PRINTF(i, j)	__attribute__((format (gnu_printf, i, j)))  #else  #define PRINTF(i, j)	__attribute__((format (printf, i, j))) @@ -65,7 +67,7 @@ extern char *xstrndup(const char *s, size_t len);  extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);  extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); -extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); +extern int PRINTF(2, 0) xavsprintf_append(char **strp, const char *fmt, va_list ap);  extern char *join_path(const char *path, const char *name);  /** diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 99614ec1a289..4c5e17639d2b 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.6.1-gabbd523b" +#define DTC_VERSION "DTC 1.7.0-g1df7b047" diff --git a/scripts/faddr2line b/scripts/faddr2line index 587415a52b6f..fe0cc45f03be 100755 --- a/scripts/faddr2line +++ b/scripts/faddr2line @@ -85,15 +85,17 @@ command -v ${ADDR2LINE} >/dev/null 2>&1 || die "${ADDR2LINE} isn't installed"  # init/main.c!  This only works for vmlinux.  Otherwise it falls back to  # printing the absolute path.  find_dir_prefix() { -	local objfile=$1 - -	local start_kernel_addr=$(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | +	local start_kernel_addr=$(echo "${ELF_SYMS}" | sed 's/\[.*\]//' |  		${AWK} '$8 == "start_kernel" {printf "0x%s", $2}')  	[[ -z $start_kernel_addr ]] && return -	local file_line=$(${ADDR2LINE} -e $objfile $start_kernel_addr) -	[[ -z $file_line ]] && return +	run_addr2line ${start_kernel_addr} "" +	[[ -z $ADDR2LINE_OUT ]] && return +	local file_line=${ADDR2LINE_OUT#* at } +	if [[ -z $file_line ]] || [[ $file_line = $ADDR2LINE_OUT ]]; then +		return +	fi  	local prefix=${file_line%init/main.c:*}  	if [[ -z $prefix ]] || [[ $prefix = $file_line ]]; then  		return @@ -103,6 +105,71 @@ find_dir_prefix() {  	return 0  } +run_readelf() { +	local objfile=$1 +	local out=$(${READELF} --file-header --section-headers --symbols --wide $objfile) + +	# This assumes that readelf first prints the file header, then the section headers, then the symbols. +	# Note: It seems that GNU readelf does not prefix section headers with the "There are X section headers" +	# line when multiple options are given, so let's also match with the "Section Headers:" line. +	ELF_FILEHEADER=$(echo "${out}" | sed -n '/There are [0-9]* section headers, starting at offset\|Section Headers:/q;p') +	ELF_SECHEADERS=$(echo "${out}" | sed -n '/There are [0-9]* section headers, starting at offset\|Section Headers:/,$p' | sed -n '/Symbol table .* contains [0-9]* entries:/q;p') +	ELF_SYMS=$(echo "${out}" | sed -n '/Symbol table .* contains [0-9]* entries:/,$p') +} + +check_vmlinux() { +	# vmlinux uses absolute addresses in the section table rather than +	# section offsets. +	IS_VMLINUX=0 +	local file_type=$(echo "${ELF_FILEHEADER}" | +		${AWK} '$1 == "Type:" { print $2; exit }') +	if [[ $file_type = "EXEC" ]] || [[ $file_type == "DYN" ]]; then +		IS_VMLINUX=1 +	fi +} + +init_addr2line() { +	local objfile=$1 + +	check_vmlinux + +	ADDR2LINE_ARGS="--functions --pretty-print --inlines --addresses --exe=$objfile" +	if [[ $IS_VMLINUX = 1 ]]; then +		# If the executable file is vmlinux, we don't pass section names to +		# addr2line, so we can launch it now as a single long-running process. +		coproc ADDR2LINE_PROC (${ADDR2LINE} ${ADDR2LINE_ARGS}) +	fi +} + +run_addr2line() { +	local addr=$1 +	local sec_name=$2 + +	if [[ $IS_VMLINUX = 1 ]]; then +		# We send to the addr2line process: (1) the address, then (2) a sentinel +		# value, i.e., something that can't be interpreted as a valid address +		# (i.e., ","). This causes addr2line to write out: (1) the answer for +		# our address, then (2) either "?? ??:0" or "0x0...0: ..." (if +		# using binutils' addr2line), or "," (if using LLVM's addr2line). +		echo ${addr} >& "${ADDR2LINE_PROC[1]}" +		echo "," >& "${ADDR2LINE_PROC[1]}" +		local first_line +		read -r first_line <& "${ADDR2LINE_PROC[0]}" +		ADDR2LINE_OUT=$(echo "${first_line}" | sed 's/^0x[0-9a-fA-F]*: //') +		while read -r line <& "${ADDR2LINE_PROC[0]}"; do +			if [[ "$line" == "?? ??:0" ]] || [[ "$line" == "," ]] || [[ $(echo "$line" | ${GREP} "^0x00*: ") ]]; then +				break +			fi +			ADDR2LINE_OUT+=$'\n'$(echo "$line" | sed 's/^0x[0-9a-fA-F]*: //') +		done +	else +		# Run addr2line as a single invocation. +		local sec_arg +		[[ -z $sec_name ]] && sec_arg="" || sec_arg="--section=${sec_name}" +		ADDR2LINE_OUT=$(${ADDR2LINE} ${ADDR2LINE_ARGS} ${sec_arg} ${addr} | sed 's/^0x[0-9a-fA-F]*: //') +	fi +} +  __faddr2line() {  	local objfile=$1  	local func_addr=$2 @@ -113,8 +180,6 @@ __faddr2line() {  	local func_offset=${func_addr#*+}  	func_offset=${func_offset%/*}  	local user_size= -	local file_type -	local is_vmlinux=0  	[[ $func_addr =~ "/" ]] && user_size=${func_addr#*/}  	if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then @@ -123,14 +188,6 @@ __faddr2line() {  		return  	fi -	# vmlinux uses absolute addresses in the section table rather than -	# section offsets. -	local file_type=$(${READELF} --file-header $objfile | -		${AWK} '$1 == "Type:" { print $2; exit }') -	if [[ $file_type = "EXEC" ]] || [[ $file_type == "DYN" ]]; then -		is_vmlinux=1 -	fi -  	# Go through each of the object's symbols which match the func name.  	# In rare cases there might be duplicates, in which case we print all  	# matches. @@ -143,8 +200,7 @@ __faddr2line() {  		local sec_name  		# Get the section size: -		sec_size=$(${READELF} --section-headers --wide $objfile | -			sed 's/\[ /\[/' | +		sec_size=$(echo "${ELF_SECHEADERS}" | sed 's/\[ /\[/' |  			${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }')  		if [[ -z $sec_size ]]; then @@ -154,8 +210,7 @@ __faddr2line() {  		fi  		# Get the section name: -		sec_name=$(${READELF} --section-headers --wide $objfile | -			sed 's/\[ /\[/' | +		sec_name=$(echo "${ELF_SECHEADERS}" | sed 's/\[ /\[/' |  			${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }')  		if [[ -z $sec_name ]]; then @@ -197,7 +252,7 @@ __faddr2line() {  				found=2  				break  			fi -		done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2) +		done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2 | ${GREP} -A1 --no-group-separator " ${sym_name}$")  		if [[ $found = 0 ]]; then  			warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size" @@ -249,9 +304,8 @@ __faddr2line() {  		# Pass section address to addr2line and strip absolute paths  		# from the output: -		local args="--functions --pretty-print --inlines --exe=$objfile" -		[[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name" -		local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;") +		run_addr2line $addr $sec_name +		local output=$(echo "${ADDR2LINE_OUT}" | sed "s; $dir_prefix\(\./\)*; ;")  		[[ -z $output ]] && continue  		# Default output (non --list): @@ -278,7 +332,7 @@ __faddr2line() {  		DONE=1 -	done < <(${READELF} --symbols --wide $objfile | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$8 == fn') +	done < <(echo "${ELF_SYMS}" | sed 's/\[.*\]//' | ${AWK} -v fn=$sym_name '$8 == fn')  }  [[ $# -lt 2 ]] && usage @@ -291,10 +345,14 @@ LIST=0  [[ ! -f $objfile ]] && die "can't find objfile $objfile"  shift -${READELF} --section-headers --wide $objfile | ${GREP} -q '\.debug_info' || die "CONFIG_DEBUG_INFO not enabled" +run_readelf $objfile + +echo "${ELF_SECHEADERS}" | ${GREP} -q '\.debug_info' || die "CONFIG_DEBUG_INFO not enabled" + +init_addr2line $objfile  DIR_PREFIX=supercalifragilisticexpialidocious -find_dir_prefix $objfile +find_dir_prefix  FIRST=1  while [[ $# -gt 0 ]]; do diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index 1ae39b9f4a95..3222c1070444 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -62,11 +62,7 @@  #include "pass_manager.h"  #include "predict.h"  #include "ipa-utils.h" - -#if BUILDING_GCC_VERSION >= 8000  #include "stringpool.h" -#endif -  #include "attribs.h"  #include "varasm.h"  #include "stor-layout.h" @@ -78,7 +74,6 @@  #include "context.h"  #include "tree-ssa-alias.h"  #include "tree-ssa.h" -#include "stringpool.h"  #if BUILDING_GCC_VERSION >= 7000  #include "tree-vrp.h"  #endif diff --git a/scripts/gdb/linux/mm.py b/scripts/gdb/linux/mm.py index 515730fd4c9d..7571aebbe650 100644 --- a/scripts/gdb/linux/mm.py +++ b/scripts/gdb/linux/mm.py @@ -33,7 +33,7 @@ class aarch64_page_ops():      def __init__(self):          self.SUBSECTION_SHIFT = 21          self.SEBSECTION_SIZE = 1 << self.SUBSECTION_SHIFT -        self.MODULES_VSIZE = 128 * 1024 * 1024 +        self.MODULES_VSIZE = 2 * 1024 * 1024 * 1024          if constants.LX_CONFIG_ARM64_64K_PAGES:              self.SECTION_SIZE_BITS = 29 @@ -47,8 +47,13 @@ class aarch64_page_ops():          self.VA_BITS = constants.LX_CONFIG_ARM64_VA_BITS          if self.VA_BITS > 48: -            self.VA_BITS_MIN = 48 -            self.vabits_actual = gdb.parse_and_eval('vabits_actual') +            if constants.LX_CONFIG_ARM64_16K_PAGES: +                self.VA_BITS_MIN = 47 +            else: +                self.VA_BITS_MIN = 48 +            tcr_el1 = gdb.execute("info registers $TCR_EL1", to_string=True) +            tcr_el1 = int(tcr_el1.split()[1], 16) +            self.vabits_actual = 64 - ((tcr_el1 >> 16) & 63)          else:              self.VA_BITS_MIN = self.VA_BITS              self.vabits_actual = self.VA_BITS @@ -59,9 +64,9 @@ class aarch64_page_ops():          if str(constants.LX_CONFIG_ARCH_FORCE_MAX_ORDER).isdigit():              self.MAX_ORDER = constants.LX_CONFIG_ARCH_FORCE_MAX_ORDER          else: -            self.MAX_ORDER = 11 +            self.MAX_ORDER = 10 -        self.MAX_ORDER_NR_PAGES = 1 << (self.MAX_ORDER - 1) +        self.MAX_ORDER_NR_PAGES = 1 << (self.MAX_ORDER)          self.PFN_SECTION_SHIFT = self.SECTION_SIZE_BITS - self.PAGE_SHIFT          self.NR_MEM_SECTIONS = 1 << self.SECTIONS_SHIFT          self.PAGES_PER_SECTION = 1 << self.PFN_SECTION_SHIFT @@ -89,10 +94,10 @@ class aarch64_page_ops():          self.MODULES_VADDR = self._PAGE_END(self.VA_BITS_MIN)          self.MODULES_END = self.MODULES_VADDR + self.MODULES_VSIZE -        self.VMEMMAP_SHIFT = (self.PAGE_SHIFT - self.STRUCT_PAGE_MAX_SHIFT) -        self.VMEMMAP_SIZE = ((self._PAGE_END(self.VA_BITS_MIN) - self.PAGE_OFFSET) >> self.VMEMMAP_SHIFT) -        self.VMEMMAP_START = (-(1 << (self.VA_BITS - self.VMEMMAP_SHIFT))) & 0xffffffffffffffff -        self.VMEMMAP_END = self.VMEMMAP_START + self.VMEMMAP_SIZE +        self.VMEMMAP_RANGE = self._PAGE_END(self.VA_BITS_MIN) - self.PAGE_OFFSET +        self.VMEMMAP_SIZE = (self.VMEMMAP_RANGE >> self.PAGE_SHIFT) * self.struct_page_size +        self.VMEMMAP_END = (-(1 * 1024 * 1024 * 1024)) & 0xffffffffffffffff +        self.VMEMMAP_START = self.VMEMMAP_END - self.VMEMMAP_SIZE          self.VMALLOC_START = self.MODULES_END          self.VMALLOC_END = self.VMEMMAP_START - 256 * 1024 * 1024 diff --git a/scripts/gdb/linux/stackdepot.py b/scripts/gdb/linux/stackdepot.py index 0281d9de4b7c..bb3a0f843931 100644 --- a/scripts/gdb/linux/stackdepot.py +++ b/scripts/gdb/linux/stackdepot.py @@ -27,14 +27,18 @@ def stack_depot_fetch(handle):      offset = parts['offset'] << DEPOT_STACK_ALIGN      pools_num = gdb.parse_and_eval('pools_num') -    if parts['pool_index'] > pools_num: +    if handle == 0: +        raise gdb.GdbError("handle is 0\n") + +    pool_index = parts['pool_index_plus_1'] - 1 +    if pool_index >= pools_num:          gdb.write("pool index %d out of bounds (%d) for stack id 0x%08x\n" % (parts['pool_index'], pools_num, handle))          return gdb.Value(0), 0      stack_pools = gdb.parse_and_eval('stack_pools')      try: -        pool = stack_pools[parts['pool_index']] +        pool = stack_pools[pool_index]          stack = (pool + gdb.Value(offset).cast(utils.get_size_t_type())).cast(stack_record_type.get_type().pointer())          size = int(stack['size'].cast(utils.get_ulong_type()))          return stack['entries'], size diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs index 641b713a033a..87f34925eb7b 100644 --- a/scripts/generate_rust_target.rs +++ b/scripts/generate_rust_target.rs @@ -169,6 +169,23 @@ fn main() {          ts.push("features", features);          ts.push("llvm-target", "x86_64-linux-gnu");          ts.push("target-pointer-width", "64"); +    } else if cfg.has("X86_32") { +        // This only works on UML, as i386 otherwise needs regparm support in rustc +        if !cfg.has("UML") { +            panic!("32-bit x86 only works under UML"); +        } +        ts.push("arch", "x86"); +        ts.push( +            "data-layout", +            "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", +        ); +        let mut features = "-3dnow,-3dnowa,-mmx,+soft-float".to_string(); +        if cfg.has("MITIGATION_RETPOLINE") { +            features += ",+retpoline-external-thunk"; +        } +        ts.push("features", features); +        ts.push("llvm-target", "i386-unknown-linux-gnu"); +        ts.push("target-pointer-width", "32");      } else if cfg.has("LOONGARCH") {          panic!("loongarch uses the builtin rustc loongarch64-unknown-none-softfloat target");      } else { diff --git a/scripts/head-object-list.txt b/scripts/head-object-list.txt index 890f69005bab..fd5d00bac447 100644 --- a/scripts/head-object-list.txt +++ b/scripts/head-object-list.txt @@ -27,7 +27,6 @@ arch/mips/kernel/head.o  arch/nios2/kernel/head.o  arch/openrisc/kernel/head.o  arch/parisc/kernel/head.o -arch/powerpc/kernel/head_40x.o  arch/powerpc/kernel/head_44x.o  arch/powerpc/kernel/head_64.o  arch/powerpc/kernel/head_8xx.o 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, <o_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(¤t_entry->sym->choice_link, +			      ¤t_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(¤t_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/kernel-doc b/scripts/kernel-doc index 95a59ac78f82..2791f8195203 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1729,6 +1729,7 @@ sub dump_function($$) {      $prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;      $prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//;      $prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//; +    $prototype =~ s/DECL_BUCKET_PARAMS\s*\(\s*(\S+)\s*,\s*(\S+)\s*\)/$1, $2/;      my $define = $prototype =~ s/^#\s*define\s+//; #ak added      $prototype =~ s/__attribute_const__ +//;      $prototype =~ s/__attribute__\s*\(\( diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh index a78b804b680c..b9513d224476 100755 --- a/scripts/ld-version.sh +++ b/scripts/ld-version.sh @@ -57,9 +57,11 @@ else  	fi  fi -# Some distributions append a package release number, as in 2.34-4.fc32 -# Trim the hyphen and any characters that follow. -version=${version%-*} +# There may be something after the version, such as a distribution's package +# release number (like Fedora's "2.34-4.fc32") or punctuation (like LLD briefly +# added before the "compatible with GNU linkers" string), so remove everything +# after just numbers and periods. +version=${version%%[!0-9.]*}  cversion=$(get_canonical_version $version)  min_cversion=$(get_canonical_version $min_version) 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 f48d72d22dc2..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;  	} @@ -776,17 +770,14 @@ static void check_section(const char *modname, struct elf_info *elf,  #define ALL_INIT_DATA_SECTIONS \ -	".init.setup", ".init.rodata", ".meminit.rodata", \ -	".init.data", ".meminit.data" +	".init.setup", ".init.rodata", ".init.data"  #define ALL_PCI_INIT_SECTIONS	\  	".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \  	".pci_fixup_enable", ".pci_fixup_resume", \  	".pci_fixup_resume_early", ".pci_fixup_suspend" -#define ALL_XXXINIT_SECTIONS ".meminit.*" - -#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS +#define ALL_INIT_SECTIONS ".init.*"  #define ALL_EXIT_SECTIONS ".exit.*"  #define DATA_SECTIONS ".data", ".data.rel" @@ -797,9 +788,7 @@ static void check_section(const char *modname, struct elf_info *elf,  		".fixup", ".entry.text", ".exception.text", \  		".coldtext", ".softirqentry.text" -#define INIT_SECTIONS      ".init.*" - -#define ALL_TEXT_SECTIONS  ".init.text", ".meminit.text", ".exit.text", \ +#define ALL_TEXT_SECTIONS  ".init.text", ".exit.text", \  		TEXT_SECTIONS, OTHER_TEXT_SECTIONS  enum mismatch { @@ -839,12 +828,6 @@ static const struct sectioncheck sectioncheck[] = {  	.bad_tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL },  	.mismatch = TEXTDATA_TO_ANY_INIT_EXIT,  }, -/* Do not reference init code/data from meminit code/data */ -{ -	.fromsec = { ALL_XXXINIT_SECTIONS, NULL }, -	.bad_tosec = { INIT_SECTIONS, NULL }, -	.mismatch = XXXINIT_TO_SOME_INIT, -},  /* Do not use exit code/data from init code */  {  	.fromsec = { ALL_INIT_SECTIONS, NULL }, @@ -859,7 +842,7 @@ static const struct sectioncheck sectioncheck[] = {  },  {  	.fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, -	.bad_tosec = { INIT_SECTIONS, NULL }, +	.bad_tosec = { ALL_INIT_SECTIONS, NULL },  	.mismatch = ANY_INIT_TO_ANY_EXIT,  },  { @@ -965,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))) @@ -1179,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; @@ -1273,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 <[email protected]> +# Contributor: Jan Alexander Steffens (heftig) <[email protected]> + +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 <[email protected]>.  # -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 fffc8af8deb1..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 @@ -83,7 +83,6 @@ ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEA  	done  	if [ -d "%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb" ];then -		echo "/lib/modules/%{KERNELRELEASE}/dtb"  		find "%{buildroot}/lib/modules/%{KERNELRELEASE}/dtb" -printf "%%%ghost /boot/dtb-%{KERNELRELEASE}/%%P\n"  	fi 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 <[email protected]>  # +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 diff --git a/scripts/spelling.txt b/scripts/spelling.txt index edec60d39bbf..554329a074ce 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -176,8 +176,10 @@ assigment||assignment  assigments||assignments  assistent||assistant  assocaited||associated +assocated||associated  assocating||associating  assocation||association +assocative||associative  associcated||associated  assotiated||associated  asssert||assert @@ -543,6 +545,7 @@ direcly||directly  direectly||directly  diregard||disregard  disassocation||disassociation +disassocative||disassociative  disapear||disappear  disapeared||disappeared  disappared||disappeared diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl new file mode 100644 index 000000000000..591d85e8ca7e --- /dev/null +++ b/scripts/syscall.tbl @@ -0,0 +1,405 @@ +# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +# +# This file contains the system call numbers for all of the +# more recently added architectures. +# +# As a basic principle, no duplication of functionality +# should be added, e.g. we don't use lseek when llseek +# is present. New architectures should use this file +# and implement the less feature-full calls in user space. +# +0	common	io_setup			sys_io_setup			compat_sys_io_setup +1	common	io_destroy			sys_io_destroy +2	common	io_submit			sys_io_submit			compat_sys_io_submit +3	common	io_cancel			sys_io_cancel +4	time32	io_getevents			sys_io_getevents_time32 +4	64	io_getevents			sys_io_getevents +5	common	setxattr			sys_setxattr +6	common	lsetxattr			sys_lsetxattr +7	common	fsetxattr			sys_fsetxattr +8	common	getxattr			sys_getxattr +9	common	lgetxattr			sys_lgetxattr +10	common	fgetxattr			sys_fgetxattr +11	common	listxattr			sys_listxattr +12	common	llistxattr			sys_llistxattr +13	common	flistxattr			sys_flistxattr +14	common	removexattr			sys_removexattr +15	common	lremovexattr			sys_lremovexattr +16	common	fremovexattr			sys_fremovexattr +17	common	getcwd				sys_getcwd +18	common	lookup_dcookie			sys_ni_syscall +19	common	eventfd2			sys_eventfd2 +20	common	epoll_create1			sys_epoll_create1 +21	common	epoll_ctl			sys_epoll_ctl +22	common	epoll_pwait			sys_epoll_pwait			compat_sys_epoll_pwait +23	common	dup				sys_dup +24	common	dup3				sys_dup3 +25	32	fcntl64				sys_fcntl64			compat_sys_fcntl64 +25	64	fcntl				sys_fcntl +26	common	inotify_init1			sys_inotify_init1 +27	common	inotify_add_watch		sys_inotify_add_watch +28	common	inotify_rm_watch		sys_inotify_rm_watch +29	common	ioctl				sys_ioctl			compat_sys_ioctl +30	common	ioprio_set			sys_ioprio_set +31	common	ioprio_get			sys_ioprio_get +32	common	flock				sys_flock +33	common	mknodat				sys_mknodat +34	common	mkdirat				sys_mkdirat +35	common	unlinkat			sys_unlinkat +36	common	symlinkat			sys_symlinkat +37	common	linkat				sys_linkat +# renameat is superseded with flags by renameat2 +38	renameat renameat			sys_renameat +39	common	umount2				sys_umount +40	common	mount				sys_mount +41	common	pivot_root			sys_pivot_root +43	32	statfs64			sys_statfs64			compat_sys_statfs64 +43	64	statfs				sys_statfs +44	32	fstatfs64			sys_fstatfs64			compat_sys_fstatfs64 +44	64	fstatfs				sys_fstatfs +45	32	truncate64			sys_truncate64			compat_sys_truncate64 +45	64	truncate			sys_truncate +46	32	ftruncate64			sys_ftruncate64			compat_sys_ftruncate64 +46	64	ftruncate			sys_ftruncate +47	common	fallocate			sys_fallocate			compat_sys_fallocate +48	common	faccessat			sys_faccessat +49	common	chdir				sys_chdir +50	common	fchdir				sys_fchdir +51	common	chroot				sys_chroot +52	common	fchmod				sys_fchmod +53	common	fchmodat			sys_fchmodat +54	common	fchownat			sys_fchownat +55	common	fchown				sys_fchown +56	common	openat				sys_openat +57	common	close				sys_close +58	common	vhangup				sys_vhangup +59	common	pipe2				sys_pipe2 +60	common	quotactl			sys_quotactl +61	common	getdents64			sys_getdents64 +62	32	llseek				sys_llseek +62	64	lseek				sys_lseek +63	common	read				sys_read +64	common	write				sys_write +65	common	readv				sys_readv			sys_readv +66	common	writev				sys_writev			sys_writev +67	common	pread64				sys_pread64			compat_sys_pread64 +68	common	pwrite64			sys_pwrite64			compat_sys_pwrite64 +69	common	preadv				sys_preadv			compat_sys_preadv +70	common	pwritev				sys_pwritev			compat_sys_pwritev +71	32	sendfile64			sys_sendfile64 +71	64	sendfile			sys_sendfile64 +72	time32	pselect6			sys_pselect6_time32		compat_sys_pselect6_time32 +72	64	pselect6			sys_pselect6 +73	time32	ppoll				sys_ppoll_time32		compat_sys_ppoll_time32 +73	64	ppoll				sys_ppoll +74	common	signalfd4			sys_signalfd4			compat_sys_signalfd4 +75	common	vmsplice			sys_vmsplice +76	common	splice				sys_splice +77	common	tee				sys_tee +78	common	readlinkat			sys_readlinkat +79	stat64	fstatat64			sys_fstatat64 +79	newstat	fstatat				sys_newfstatat +80	stat64	fstat64				sys_fstat64 +80	newstat	fstat				sys_newfstat +81	common	sync				sys_sync +82	common	fsync				sys_fsync +83	common	fdatasync			sys_fdatasync +84	common	sync_file_range			sys_sync_file_range		compat_sys_sync_file_range +85	common	timerfd_create			sys_timerfd_create +86	time32	timerfd_settime			sys_timerfd_settime32 +86	64	timerfd_settime			sys_timerfd_settime +87	time32	timerfd_gettime			sys_timerfd_gettime32 +87	64	timerfd_gettime			sys_timerfd_gettime +88	time32	utimensat			sys_utimensat_time32 +88	64	utimensat			sys_utimensat +89	common	acct				sys_acct +90	common	capget				sys_capget +91	common	capset				sys_capset +92	common	personality			sys_personality +93	common	exit				sys_exit +94	common	exit_group			sys_exit_group +95	common	waitid				sys_waitid			compat_sys_waitid +96	common	set_tid_address			sys_set_tid_address +97	common	unshare				sys_unshare +98	time32	futex				sys_futex_time32 +98	64	futex				sys_futex +99	common	set_robust_list			sys_set_robust_list		compat_sys_set_robust_list +100	common	get_robust_list			sys_get_robust_list		compat_sys_get_robust_list +101	time32	nanosleep			sys_nanosleep_time32 +101	64	nanosleep			sys_nanosleep +102	common	getitimer			sys_getitimer			compat_sys_getitimer +103	common	setitimer			sys_setitimer			compat_sys_setitimer +104	common	kexec_load			sys_kexec_load			compat_sys_kexec_load +105	common	init_module			sys_init_module +106	common	delete_module			sys_delete_module +107	common	timer_create			sys_timer_create		compat_sys_timer_create +108	time32	timer_gettime			sys_timer_gettime32 +108	64	timer_gettime			sys_timer_gettime +109	common	timer_getoverrun		sys_timer_getoverrun +110	time32	timer_settime			sys_timer_settime32 +110	64	timer_settime			sys_timer_settime +111	common	timer_delete			sys_timer_delete +112	time32	clock_settime			sys_clock_settime32 +112	64	clock_settime			sys_clock_settime +113	time32	clock_gettime			sys_clock_gettime32 +113	64	clock_gettime			sys_clock_gettime +114	time32	clock_getres			sys_clock_getres_time32 +114	64	clock_getres			sys_clock_getres +115	time32	clock_nanosleep			sys_clock_nanosleep_time32 +115	64	clock_nanosleep			sys_clock_nanosleep +116	common	syslog				sys_syslog +117	common	ptrace				sys_ptrace			compat_sys_ptrace +118	common	sched_setparam			sys_sched_setparam +119	common	sched_setscheduler		sys_sched_setscheduler +120	common	sched_getscheduler		sys_sched_getscheduler +121	common	sched_getparam			sys_sched_getparam +122	common	sched_setaffinity		sys_sched_setaffinity		compat_sys_sched_setaffinity +123	common	sched_getaffinity		sys_sched_getaffinity		compat_sys_sched_getaffinity +124	common	sched_yield			sys_sched_yield +125	common	sched_get_priority_max		sys_sched_get_priority_max +126	common	sched_get_priority_min		sys_sched_get_priority_min +127	time32	sched_rr_get_interval		sys_sched_rr_get_interval_time32 +127	64	sched_rr_get_interval		sys_sched_rr_get_interval +128	common	restart_syscall			sys_restart_syscall +129	common	kill				sys_kill +130	common	tkill				sys_tkill +131	common	tgkill				sys_tgkill +132	common	sigaltstack			sys_sigaltstack			compat_sys_sigaltstack +133	common	rt_sigsuspend			sys_rt_sigsuspend		compat_sys_rt_sigsuspend +134	common	rt_sigaction			sys_rt_sigaction		compat_sys_rt_sigaction +135	common	rt_sigprocmask			sys_rt_sigprocmask		compat_sys_rt_sigprocmask +136	common	rt_sigpending			sys_rt_sigpending		compat_sys_rt_sigpending +137	time32	rt_sigtimedwait			sys_rt_sigtimedwait_time32	compat_sys_rt_sigtimedwait_time32 +137	64	rt_sigtimedwait			sys_rt_sigtimedwait +138	common	rt_sigqueueinfo			sys_rt_sigqueueinfo		compat_sys_rt_sigqueueinfo +139	common	rt_sigreturn			sys_rt_sigreturn		compat_sys_rt_sigreturn +140	common	setpriority			sys_setpriority +141	common	getpriority			sys_getpriority +142	common	reboot				sys_reboot +143	common	setregid			sys_setregid +144	common	setgid				sys_setgid +145	common	setreuid			sys_setreuid +146	common	setuid				sys_setuid +147	common	setresuid			sys_setresuid +148	common	getresuid			sys_getresuid +149	common	setresgid			sys_setresgid +150	common	getresgid			sys_getresgid +151	common	setfsuid			sys_setfsuid +152	common	setfsgid			sys_setfsgid +153	common	times				sys_times			compat_sys_times +154	common	setpgid				sys_setpgid +155	common	getpgid				sys_getpgid +156	common	getsid				sys_getsid +157	common	setsid				sys_setsid +158	common	getgroups			sys_getgroups +159	common	setgroups			sys_setgroups +160	common	uname				sys_newuname +161	common	sethostname			sys_sethostname +162	common	setdomainname			sys_setdomainname +# getrlimit and setrlimit are superseded with prlimit64 +163	rlimit	getrlimit			sys_getrlimit			compat_sys_getrlimit +164	rlimit	setrlimit			sys_setrlimit			compat_sys_setrlimit +165	common	getrusage			sys_getrusage			compat_sys_getrusage +166	common	umask				sys_umask +167	common	prctl				sys_prctl +168	common	getcpu				sys_getcpu +169	time32	gettimeofday			sys_gettimeofday		compat_sys_gettimeofday +169	64	gettimeofday			sys_gettimeofday +170	time32	settimeofday			sys_settimeofday		compat_sys_settimeofday +170	64	settimeofday			sys_settimeofday +171	time32	adjtimex			sys_adjtimex_time32 +171	64	adjtimex			sys_adjtimex +172	common	getpid				sys_getpid +173	common	getppid				sys_getppid +174	common	getuid				sys_getuid +175	common	geteuid				sys_geteuid +176	common	getgid				sys_getgid +177	common	getegid				sys_getegid +178	common	gettid				sys_gettid +179	common	sysinfo				sys_sysinfo			compat_sys_sysinfo +180	common	mq_open				sys_mq_open			compat_sys_mq_open +181	common	mq_unlink			sys_mq_unlink +182	time32	mq_timedsend			sys_mq_timedsend_time32 +182	64	mq_timedsend			sys_mq_timedsend +183	time32	mq_timedreceive			sys_mq_timedreceive_time32 +183	64	mq_timedreceive			sys_mq_timedreceive +184	common	mq_notify			sys_mq_notify			compat_sys_mq_notify +185	common	mq_getsetattr			sys_mq_getsetattr		compat_sys_mq_getsetattr +186	common	msgget				sys_msgget +187	common	msgctl				sys_msgctl			compat_sys_msgctl +188	common	msgrcv				sys_msgrcv			compat_sys_msgrcv +189	common	msgsnd				sys_msgsnd			compat_sys_msgsnd +190	common	semget				sys_semget +191	common	semctl				sys_semctl			compat_sys_semctl +192	time32	semtimedop			sys_semtimedop_time32 +192	64	semtimedop			sys_semtimedop +193	common	semop				sys_semop +194	common	shmget				sys_shmget +195	common	shmctl				sys_shmctl			compat_sys_shmctl +196	common	shmat				sys_shmat			compat_sys_shmat +197	common	shmdt				sys_shmdt +198	common	socket				sys_socket +199	common	socketpair			sys_socketpair +200	common	bind				sys_bind +201	common	listen				sys_listen +202	common	accept				sys_accept +203	common	connect				sys_connect +204	common	getsockname			sys_getsockname +205	common	getpeername			sys_getpeername +206	common	sendto				sys_sendto +207	common	recvfrom			sys_recvfrom			compat_sys_recvfrom +208	common	setsockopt			sys_setsockopt			sys_setsockopt +209	common	getsockopt			sys_getsockopt			sys_getsockopt +210	common	shutdown			sys_shutdown +211	common	sendmsg				sys_sendmsg			compat_sys_sendmsg +212	common	recvmsg				sys_recvmsg			compat_sys_recvmsg +213	common	readahead			sys_readahead			compat_sys_readahead +214	common	brk				sys_brk +215	common	munmap				sys_munmap +216	common	mremap				sys_mremap +217	common	add_key				sys_add_key +218	common	request_key			sys_request_key +219	common	keyctl				sys_keyctl			compat_sys_keyctl +220	common	clone				sys_clone +221	common	execve				sys_execve			compat_sys_execve +222	32	mmap2				sys_mmap2 +222	64	mmap				sys_mmap +223	32	fadvise64_64			sys_fadvise64_64		compat_sys_fadvise64_64 +223	64	fadvise64			sys_fadvise64_64 +224	common	swapon				sys_swapon +225	common	swapoff				sys_swapoff +226	common	mprotect			sys_mprotect +227	common	msync				sys_msync +228	common	mlock				sys_mlock +229	common	munlock				sys_munlock +230	common	mlockall			sys_mlockall +231	common	munlockall			sys_munlockall +232	common	mincore				sys_mincore +233	common	madvise				sys_madvise +234	common	remap_file_pages		sys_remap_file_pages +235	common	mbind				sys_mbind +236	common	get_mempolicy			sys_get_mempolicy +237	common	set_mempolicy			sys_set_mempolicy +238	common	migrate_pages			sys_migrate_pages +239	common	move_pages			sys_move_pages +240	common	rt_tgsigqueueinfo		sys_rt_tgsigqueueinfo		compat_sys_rt_tgsigqueueinfo +241	common	perf_event_open			sys_perf_event_open +242	common	accept4				sys_accept4 +243	time32	recvmmsg			sys_recvmmsg_time32		compat_sys_recvmmsg_time32 +243	64	recvmmsg			sys_recvmmsg +# Architectures may provide up to 16 syscalls of their own between 244 and 259 +244	arc	cacheflush			sys_cacheflush +245	arc	arc_settls			sys_arc_settls +246	arc	arc_gettls			sys_arc_gettls +247	arc	sysfs				sys_sysfs +248	arc	arc_usr_cmpxchg			sys_arc_usr_cmpxchg + +244	csky	set_thread_area			sys_set_thread_area +245	csky	cacheflush			sys_cacheflush + +244	nios2	cacheflush			sys_cacheflush + +244	or1k	or1k_atomic			sys_or1k_atomic + +258	riscv	riscv_hwprobe			sys_riscv_hwprobe +259	riscv	riscv_flush_icache		sys_riscv_flush_icache + +260	time32	wait4				sys_wait4			compat_sys_wait4 +260	64	wait4				sys_wait4 +261	common	prlimit64			sys_prlimit64 +262	common	fanotify_init			sys_fanotify_init +263	common	fanotify_mark			sys_fanotify_mark +264	common	name_to_handle_at		sys_name_to_handle_at +265	common	open_by_handle_at		sys_open_by_handle_at +266	time32	clock_adjtime			sys_clock_adjtime32 +266	64	clock_adjtime			sys_clock_adjtime +267	common	syncfs				sys_syncfs +268	common	setns				sys_setns +269	common	sendmmsg			sys_sendmmsg			compat_sys_sendmmsg +270	common	process_vm_readv		sys_process_vm_readv +271	common	process_vm_writev		sys_process_vm_writev +272	common	kcmp				sys_kcmp +273	common	finit_module			sys_finit_module +274	common	sched_setattr			sys_sched_setattr +275	common	sched_getattr			sys_sched_getattr +276	common	renameat2			sys_renameat2 +277	common	seccomp				sys_seccomp +278	common	getrandom			sys_getrandom +279	common	memfd_create			sys_memfd_create +280	common	bpf				sys_bpf +281	common	execveat			sys_execveat			compat_sys_execveat +282	common	userfaultfd			sys_userfaultfd +283	common	membarrier			sys_membarrier +284	common	mlock2				sys_mlock2 +285	common	copy_file_range			sys_copy_file_range +286	common	preadv2				sys_preadv2			compat_sys_preadv2 +287	common	pwritev2			sys_pwritev2			compat_sys_pwritev2 +288	common	pkey_mprotect			sys_pkey_mprotect +289	common	pkey_alloc			sys_pkey_alloc +290	common	pkey_free			sys_pkey_free +291	common	statx				sys_statx +292	time32	io_pgetevents			sys_io_pgetevents_time32	compat_sys_io_pgetevents +292	64	io_pgetevents			sys_io_pgetevents +293	common	rseq				sys_rseq +294	common	kexec_file_load			sys_kexec_file_load +# 295 through 402 are unassigned to sync up with generic numbers don't use +403	32	clock_gettime64			sys_clock_gettime +404	32	clock_settime64			sys_clock_settime +405	32	clock_adjtime64			sys_clock_adjtime +406	32	clock_getres_time64		sys_clock_getres +407	32	clock_nanosleep_time64		sys_clock_nanosleep +408	32	timer_gettime64			sys_timer_gettime +409	32	timer_settime64			sys_timer_settime +410	32	timerfd_gettime64		sys_timerfd_gettime +411	32	timerfd_settime64		sys_timerfd_settime +412	32	utimensat_time64		sys_utimensat +413	32	pselect6_time64			sys_pselect6			compat_sys_pselect6_time64 +414	32	ppoll_time64			sys_ppoll			compat_sys_ppoll_time64 +416	32	io_pgetevents_time64		sys_io_pgetevents		compat_sys_io_pgetevents_time64 +417	32	recvmmsg_time64			sys_recvmmsg			compat_sys_recvmmsg_time64 +418	32	mq_timedsend_time64		sys_mq_timedsend +419	32	mq_timedreceive_time64		sys_mq_timedreceive +420	32	semtimedop_time64		sys_semtimedop +421	32	rt_sigtimedwait_time64		sys_rt_sigtimedwait		compat_sys_rt_sigtimedwait_time64 +422	32	futex_time64			sys_futex +423	32	sched_rr_get_interval_time64	sys_sched_rr_get_interval +424	common	pidfd_send_signal		sys_pidfd_send_signal +425	common	io_uring_setup			sys_io_uring_setup +426	common	io_uring_enter			sys_io_uring_enter +427	common	io_uring_register		sys_io_uring_register +428	common	open_tree			sys_open_tree +429	common	move_mount			sys_move_mount +430	common	fsopen				sys_fsopen +431	common	fsconfig			sys_fsconfig +432	common	fsmount				sys_fsmount +433	common	fspick				sys_fspick +434	common	pidfd_open			sys_pidfd_open +435	common	clone3				sys_clone3 +436	common	close_range			sys_close_range +437	common	openat2				sys_openat2 +438	common	pidfd_getfd			sys_pidfd_getfd +439	common	faccessat2			sys_faccessat2 +440	common	process_madvise			sys_process_madvise +441	common	epoll_pwait2			sys_epoll_pwait2		compat_sys_epoll_pwait2 +442	common	mount_setattr			sys_mount_setattr +443	common	quotactl_fd			sys_quotactl_fd +444	common	landlock_create_ruleset		sys_landlock_create_ruleset +445	common	landlock_add_rule		sys_landlock_add_rule +446	common	landlock_restrict_self		sys_landlock_restrict_self +447	memfd_secret	memfd_secret		sys_memfd_secret +448	common	process_mrelease		sys_process_mrelease +449	common	futex_waitv			sys_futex_waitv +450	common	set_mempolicy_home_node		sys_set_mempolicy_home_node +451	common	cachestat			sys_cachestat +452	common	fchmodat2			sys_fchmodat2 +453	common	map_shadow_stack		sys_map_shadow_stack +454	common	futex_wake			sys_futex_wake +455	common	futex_wait			sys_futex_wait +456	common	futex_requeue			sys_futex_requeue +457	common	statmount			sys_statmount +458	common	listmount			sys_listmount +459	common	lsm_get_self_attr		sys_lsm_get_self_attr +460	common	lsm_set_self_attr		sys_lsm_set_self_attr +461	common	lsm_list_modules		sys_lsm_list_modules +462	common	mseal				sys_mseal +467	common	uretprobe			sys_uretprobe diff --git a/scripts/syscalltbl.sh b/scripts/syscalltbl.sh index 6abe143889ef..6a903b87a7c2 100755 --- a/scripts/syscalltbl.sh +++ b/scripts/syscalltbl.sh @@ -54,7 +54,7 @@ nxt=0  grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | { -	while read nr abi name native compat ; do +	while read nr abi name native compat noreturn; do  		if [ $nxt -gt $nr ]; then  			echo "error: $infile: syscall table is not sorted or duplicates the same syscall number" >&2 @@ -66,7 +66,21 @@ grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | {  			nxt=$((nxt + 1))  		done -		if [ -n "$compat" ]; then +		if [ "$compat" = "-" ]; then +			unset compat +		fi + +		if [ -n "$noreturn" ]; then +			if [ "$noreturn" != "noreturn" ]; then +				echo "error: $infile: invalid string \"$noreturn\" in 'noreturn' column" +				exit 1 +			fi +			if [ -n "$compat" ]; then +				echo "__SYSCALL_COMPAT_NORETURN($nr, $native, $compat)" +			else +				echo "__SYSCALL_NORETURN($nr, $native)" +			fi +		elif [ -n "$compat" ]; then  			echo "__SYSCALL_WITH_COMPAT($nr, $native, $compat)"  		elif [ -n "$native" ]; then  			echo "__SYSCALL($nr, $native)" |