mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-07 19:38:16 +00:00
Kbuild updates for v6.11
- Remove tristate choice support from Kconfig - Stop using the PROVIDE() directive in the linker script - Reduce the number of links for the combination of CONFIG_DEBUG_INFO_BTF and CONFIG_KALLSYMS - Enable the warning for symbol reference to .exit.* sections by default - Fix warnings in RPM package builds - Improve scripts/make_fit.py to generate a FIT image with separate base DTB and overlays - Improve choice value calculation in Kconfig - Fix conditional prompt behavior in choice in Kconfig - Remove support for the uncommon EMAIL environment variable in Debian package builds - Remove support for the uncommon "name <email>" form for the DEBEMAIL environment variable - Raise the minimum supported GNU Make version to 4.0 - Remove stale code for the absolute kallsyms - Move header files commonly used for host programs to scripts/include/ - Introduce the pacman-pkg target to generate a pacman package used in Arch Linux - Clean up Kconfig -----BEGIN PGP SIGNATURE----- iQJJBAABCgAzFiEEbmPs18K1szRHjPqEPYsBB53g2wYFAmagBLUVHG1hc2FoaXJv eUBrZXJuZWwub3JnAAoJED2LAQed4NsGmoUQAJ8pnURs0g+Rcyk6bdY/qtXBYkS+ nXpIK1ssFgRRgAQdeszYtvBqLFzb0wRCSie87G1AriD/JkVVTjCCY1For1y+vs0u a7HfxitHhZpPyZW/T+WMQ3LViNccpkx+DFAcoRH8xOY/XPEJKVUby332jOIXMuyg +NKIELQJVsLhcDofTUGb5VfIQektw219n5c4jKjXdNk4ZtE24xCRM5X528ZebwWJ RZhMvJ968PyIH1IRXvNt6dsKBxoGIwPP8IO6yW9hzHaNsBqt7MGSChSel7r1VKpk iwCNApJvEiVBe5wvTSVOVro7/8p/AZ70CQAqnMJV+dNnRqtGqW7NvL6XAjZRJgJJ Uxe5NSrXgQd3FtqfcbXLetBgp9zGVt328nHm1HXHR5rFsvoOiTvO7hHPbhA+OoWJ fs+jHzEXdAMRgsNrczPWU5Svq6MgGe4v8HBf0m8N1Uy65t/O+z9ti2QAw7kIFlbu /VSFNjw4CHmNxGhnH0khCMsy85FwVIt9Ux+2d6IEc0gP8S1Qa1HgHGAoVI4U51eS 9dxEPVJNPOugaIVHheuS3wimEO6wzaJcQHn4IXaasMA7P6Yo4G/jiGoy4cb9qPTM Hb+GaOltUy7vDoG4D2LSym8zR8rdKwbIf/5psdZrq/IWVKq5p+p7KWs3aOykSoM7 o6Hb532Ioalhm8je =BYu7 -----END PGP SIGNATURE----- Merge tag 'kbuild-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild Pull Kbuild updates from Masahiro Yamada: - Remove tristate choice support from Kconfig - Stop using the PROVIDE() directive in the linker script - Reduce the number of links for the combination of CONFIG_KALLSYMS and CONFIG_DEBUG_INFO_BTF - Enable the warning for symbol reference to .exit.* sections by default - Fix warnings in RPM package builds - Improve scripts/make_fit.py to generate a FIT image with separate base DTB and overlays - Improve choice value calculation in Kconfig - Fix conditional prompt behavior in choice in Kconfig - Remove support for the uncommon EMAIL environment variable in Debian package builds - Remove support for the uncommon "name <email>" form for the DEBEMAIL environment variable - Raise the minimum supported GNU Make version to 4.0 - Remove stale code for the absolute kallsyms - Move header files commonly used for host programs to scripts/include/ - Introduce the pacman-pkg target to generate a pacman package used in Arch Linux - Clean up Kconfig * tag 'kbuild-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (65 commits) kbuild: doc: gcc to CC change kallsyms: change sym_entry::percpu_absolute to bool type kallsyms: unify seq and start_pos fields of struct sym_entry kallsyms: add more original symbol type/name in comment lines kallsyms: use \t instead of a tab in printf() kallsyms: avoid repeated calculation of array size for markers kbuild: add script and target to generate pacman package modpost: use generic macros for hash table implementation kbuild: move some helper headers from scripts/kconfig/ to scripts/include/ Makefile: add comment to discourage tools/* addition for kernel builds kbuild: clean up scripts/remove-stale-files kconfig: recursive checks drop file/lineno kbuild: rpm-pkg: introduce a simple changelog section for kernel.spec kallsyms: get rid of code for absolute kallsyms kbuild: Create INSTALL_PATH directory if it does not exist kbuild: Abort make on install failures kconfig: remove 'e1' and 'e2' macros from expression deduplication kconfig: remove SYMBOL_CHOICEVAL flag kconfig: add const qualifiers to several function arguments kconfig: call expr_eliminate_yn() at least once in expr_eliminate_dups() ...
This commit is contained in:
commit
ca83c61cb3
95 changed files with 1017 additions and 1468 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -92,6 +92,12 @@ modules.order
|
|||
#
|
||||
/tar-install/
|
||||
|
||||
#
|
||||
# pacman files (make pacman-pkg)
|
||||
#
|
||||
/PKGBUILD
|
||||
/pacman/
|
||||
|
||||
#
|
||||
# We don't want to ignore the following even if they are dot-files
|
||||
#
|
||||
|
|
|
@ -409,16 +409,9 @@ choices::
|
|||
"endchoice"
|
||||
|
||||
This defines a choice group and accepts any of the above attributes as
|
||||
options. A choice can only be of type bool or tristate. If no type is
|
||||
specified for a choice, its type will be determined by the type of
|
||||
the first choice element in the group or remain unknown if none of the
|
||||
choice elements have a type specified, as well.
|
||||
options.
|
||||
|
||||
While a boolean choice only allows a single config entry to be
|
||||
selected, a tristate choice also allows any number of config entries
|
||||
to be set to 'm'. This can be used if multiple drivers for a single
|
||||
hardware exists and only a single driver can be compiled/loaded into
|
||||
the kernel, but all drivers can be compiled as modules.
|
||||
A choice only allows a single config entry to be selected.
|
||||
|
||||
comment::
|
||||
|
||||
|
|
|
@ -578,7 +578,7 @@ cc-option
|
|||
Note: cc-option uses KBUILD_CFLAGS for $(CC) options
|
||||
|
||||
cc-option-yn
|
||||
cc-option-yn is used to check if gcc supports a given option
|
||||
cc-option-yn is used to check if $(CC) supports a given option
|
||||
and return "y" if supported, otherwise "n".
|
||||
|
||||
Example::
|
||||
|
@ -596,7 +596,7 @@ cc-option-yn
|
|||
Note: cc-option-yn uses KBUILD_CFLAGS for $(CC) options
|
||||
|
||||
cc-disable-warning
|
||||
cc-disable-warning checks if gcc supports a given warning and returns
|
||||
cc-disable-warning checks if $(CC) supports a given warning and returns
|
||||
the commandline switch to disable it. This special function is needed,
|
||||
because gcc 4.4 and later accept any unknown -Wno-* option and only
|
||||
warn about it if there is another warning in the source file.
|
||||
|
@ -606,7 +606,7 @@ cc-disable-warning
|
|||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
|
||||
|
||||
In the above example, -Wno-unused-but-set-variable will be added to
|
||||
KBUILD_CFLAGS only if gcc really accepts it.
|
||||
KBUILD_CFLAGS only if $(CC) really accepts it.
|
||||
|
||||
gcc-min-version
|
||||
gcc-min-version tests if the value of $(CONFIG_GCC_VERSION) is greater than
|
||||
|
|
|
@ -33,7 +33,7 @@ GNU C 5.1 gcc --version
|
|||
Clang/LLVM (optional) 13.0.1 clang --version
|
||||
Rust (optional) 1.78.0 rustc --version
|
||||
bindgen (optional) 0.65.1 bindgen --version
|
||||
GNU make 3.82 make --version
|
||||
GNU make 4.0 make --version
|
||||
bash 4.2 bash --version
|
||||
binutils 2.25 ld -v
|
||||
flex 2.5.35 flex --version
|
||||
|
@ -112,7 +112,7 @@ It depends on ``libclang``.
|
|||
Make
|
||||
----
|
||||
|
||||
You will need GNU make 3.82 or later to build the kernel.
|
||||
You will need GNU make 4.0 or later to build the kernel.
|
||||
|
||||
Bash
|
||||
----
|
||||
|
|
|
@ -12117,6 +12117,7 @@ F: scripts/Makefile*
|
|||
F: scripts/basic/
|
||||
F: scripts/clang-tools/
|
||||
F: scripts/dummy-tools/
|
||||
F: scripts/include/
|
||||
F: scripts/mk*
|
||||
F: scripts/mod/
|
||||
F: scripts/package/
|
||||
|
@ -12172,6 +12173,13 @@ F: include/uapi/linux/nfsd/
|
|||
F: include/uapi/linux/sunrpc/
|
||||
F: net/sunrpc/
|
||||
|
||||
KERNEL PACMAN PACKAGING (in addition to generic KERNEL BUILD)
|
||||
M: Thomas Weißschuh <linux@weissschuh.net>
|
||||
R: Christian Heusel <christian@heusel.eu>
|
||||
R: Nathan Chancellor <nathan@kernel.org>
|
||||
S: Maintained
|
||||
F: scripts/package/PKGBUILD
|
||||
|
||||
KERNEL REGRESSIONS
|
||||
M: Thorsten Leemhuis <linux@leemhuis.info>
|
||||
L: regressions@lists.linux.dev
|
||||
|
|
36
Makefile
36
Makefile
|
@ -11,8 +11,8 @@ NAME = Baby Opossum Posse
|
|||
# Comments in this file are targeted only to the developer, do not
|
||||
# expect to learn how to build the kernel reading this file.
|
||||
|
||||
ifeq ($(filter undefine,$(.FEATURES)),)
|
||||
$(error GNU Make >= 3.82 is required. Your Make version is $(MAKE_VERSION))
|
||||
ifeq ($(filter output-sync,$(.FEATURES)),)
|
||||
$(error GNU Make >= 4.0 is required. Your Make version is $(MAKE_VERSION))
|
||||
endif
|
||||
|
||||
$(if $(filter __%, $(MAKECMDGOALS)), \
|
||||
|
@ -93,15 +93,7 @@ endif
|
|||
|
||||
# If the user is running make -s (silent mode), suppress echoing of
|
||||
# commands
|
||||
# make-4.0 (and later) keep single letter options in the 1st word of MAKEFLAGS.
|
||||
|
||||
ifeq ($(filter 3.%,$(MAKE_VERSION)),)
|
||||
short-opts := $(firstword -$(MAKEFLAGS))
|
||||
else
|
||||
short-opts := $(filter-out --%,$(MAKEFLAGS))
|
||||
endif
|
||||
|
||||
ifneq ($(findstring s,$(short-opts)),)
|
||||
ifneq ($(findstring s,$(firstword -$(MAKEFLAGS))),)
|
||||
quiet=silent_
|
||||
override KBUILD_VERBOSE :=
|
||||
endif
|
||||
|
@ -201,14 +193,6 @@ ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
|
|||
$(error source directory cannot contain spaces or colons)
|
||||
endif
|
||||
|
||||
ifneq ($(filter 3.%,$(MAKE_VERSION)),)
|
||||
# 'MAKEFLAGS += -rR' does not immediately become effective for GNU Make 3.x
|
||||
# We need to invoke sub-make to avoid implicit rules in the top Makefile.
|
||||
need-sub-make := 1
|
||||
# Cancel implicit rules for this Makefile.
|
||||
$(this-makefile): ;
|
||||
endif
|
||||
|
||||
export sub_make_done := 1
|
||||
|
||||
endif # sub_make_done
|
||||
|
@ -474,8 +458,10 @@ export rust_common_flags := --edition=2021 \
|
|||
-Dclippy::no_mangle_with_rust_abi \
|
||||
-Wclippy::dbg_macro
|
||||
|
||||
KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(HOST_LFS_CFLAGS) $(HOSTCFLAGS)
|
||||
KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS)
|
||||
KBUILD_HOSTCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(HOST_LFS_CFLAGS) \
|
||||
$(HOSTCFLAGS) -I $(srctree)/scripts/include
|
||||
KBUILD_HOSTCXXFLAGS := -Wall -O2 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS) \
|
||||
-I $(srctree)/scripts/include
|
||||
KBUILD_HOSTRUSTFLAGS := $(rust_common_flags) -O -Cstrip=debuginfo \
|
||||
-Zallow-features= $(HOSTRUSTFLAGS)
|
||||
KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS)
|
||||
|
@ -1344,6 +1330,12 @@ prepare: tools/bpf/resolve_btfids
|
|||
endif
|
||||
endif
|
||||
|
||||
# The tools build system is not a part of Kbuild and tends to introduce
|
||||
# its own unique issues. If you need to integrate a new tool into Kbuild,
|
||||
# please consider locating that tool outside the tools/ tree and using the
|
||||
# standard Kbuild "hostprogs" syntax instead of adding a new tools/* entry
|
||||
# here. See Documentation/kbuild/makefiles.rst for details.
|
||||
|
||||
PHONY += resolve_btfids_clean
|
||||
|
||||
resolve_btfids_O = $(abspath $(objtree))/tools/bpf/resolve_btfids
|
||||
|
@ -1497,7 +1489,7 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
|
|||
# Directories & files removed with 'make mrproper'
|
||||
MRPROPER_FILES += include/config include/generated \
|
||||
arch/$(SRCARCH)/include/generated .objdiff \
|
||||
debian snap tar-install \
|
||||
debian snap tar-install PKGBUILD pacman \
|
||||
.config .config.old .version \
|
||||
Module.symvers \
|
||||
certs/signing_key.pem \
|
||||
|
|
|
@ -1483,7 +1483,8 @@ config ARM_ATAG_DTB_COMPAT
|
|||
from the ATAG list and store it at run time into the appended DTB.
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type" if ARM_ATAG_DTB_COMPAT
|
||||
prompt "Kernel command line type"
|
||||
depends on ARM_ATAG_DTB_COMPAT
|
||||
default ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER
|
||||
|
||||
config ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER
|
||||
|
@ -1512,7 +1513,8 @@ config CMDLINE
|
|||
memory size and the root device (e.g., mem=64M root=/dev/nfs).
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type" if CMDLINE != ""
|
||||
prompt "Kernel command line type"
|
||||
depends on CMDLINE != ""
|
||||
default CMDLINE_FROM_BOOTLOADER
|
||||
|
||||
config CMDLINE_FROM_BOOTLOADER
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(basename $2)" = "zImage" ]; then
|
||||
# Compressed install
|
||||
echo "Installing compressed kernel"
|
||||
|
|
|
@ -2290,7 +2290,8 @@ config CMDLINE
|
|||
root device (e.g. root=/dev/nfs).
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type" if CMDLINE != ""
|
||||
prompt "Kernel command line type"
|
||||
depends on CMDLINE != ""
|
||||
default CMDLINE_FROM_BOOTLOADER
|
||||
help
|
||||
Choose how the kernel will handle the provided default kernel
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(basename $2)" = "Image.gz" ] || [ "$(basename $2)" = "vmlinuz.efi" ]
|
||||
then
|
||||
# Compressed install
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ -f $4/vmlinuz ]; then
|
||||
mv $4/vmlinuz $4/vmlinuz.old
|
||||
fi
|
||||
|
|
|
@ -2927,7 +2927,8 @@ config BUILTIN_DTB
|
|||
bool
|
||||
|
||||
choice
|
||||
prompt "Kernel appended dtb support" if USE_OF
|
||||
prompt "Kernel appended dtb support"
|
||||
depends on USE_OF
|
||||
default MIPS_NO_APPENDED_DTB
|
||||
|
||||
config MIPS_NO_APPENDED_DTB
|
||||
|
@ -2968,7 +2969,8 @@ choice
|
|||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type" if !CMDLINE_OVERRIDE
|
||||
prompt "Kernel command line type"
|
||||
depends on !CMDLINE_OVERRIDE
|
||||
default MIPS_CMDLINE_FROM_DTB if USE_OF && !ATH79 && !MACH_INGENIC && \
|
||||
!MACH_LOONGSON64 && !MIPS_MALTA && \
|
||||
!CAVIUM_OCTEON_SOC
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ -f $4/vmlinuz ]; then
|
||||
mv $4/vmlinuz $4/vmlinuz.old
|
||||
fi
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(basename $2)" = "vmlinuz" ]; then
|
||||
# Compressed install
|
||||
echo "Installing compressed kernel"
|
||||
|
|
|
@ -964,7 +964,8 @@ config CMDLINE
|
|||
most cases you will need to specify the root device here.
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type" if CMDLINE != ""
|
||||
prompt "Kernel command line type"
|
||||
depends on CMDLINE != ""
|
||||
default CMDLINE_FROM_BOOTLOADER
|
||||
|
||||
config CMDLINE_FROM_BOOTLOADER
|
||||
|
|
|
@ -960,7 +960,8 @@ config CMDLINE
|
|||
line here and choose how the kernel should use it later on.
|
||||
|
||||
choice
|
||||
prompt "Built-in command line usage" if CMDLINE != ""
|
||||
prompt "Built-in command line usage"
|
||||
depends on CMDLINE != ""
|
||||
default CMDLINE_FALLBACK
|
||||
help
|
||||
Choose how the kernel will handle the provided built-in command
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
case "${2##*/}" in
|
||||
# Compressed install
|
||||
Image.*|vmlinuz.efi)
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
echo "Warning: '${INSTALLKERNEL}' command not available - additional " \
|
||||
"bootloader config required" >&2
|
||||
if [ -f "$4/vmlinuz-$1" ]; then mv -- "$4/vmlinuz-$1" "$4/vmlinuz-$1.old"; fi
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ -f $4/vmlinuz ]; then
|
||||
mv $4/vmlinuz $4/vmlinuz.old
|
||||
fi
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
set -e
|
||||
|
||||
if [ -f $4/vmlinuz ]; then
|
||||
mv $4/vmlinuz $4/vmlinuz.old
|
||||
fi
|
||||
|
|
|
@ -151,8 +151,9 @@ config JFFS2_RUBIN
|
|||
RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
|
||||
|
||||
choice
|
||||
prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
|
||||
prompt "JFFS2 default compression mode"
|
||||
default JFFS2_CMODE_PRIORITY
|
||||
depends on JFFS2_COMPRESSION_OPTIONS
|
||||
depends on JFFS2_FS
|
||||
help
|
||||
You can set here the default compression mode of JFFS2 from
|
||||
|
|
|
@ -442,30 +442,11 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some symbol definitions will not exist yet during the first pass of the
|
||||
* link, but are guaranteed to exist in the final link. Provide preliminary
|
||||
* definitions that will be superseded in the final link to avoid having to
|
||||
* rely on weak external linkage, which requires a GOT when used in position
|
||||
* independent code.
|
||||
*/
|
||||
#define PRELIMINARY_SYMBOL_DEFINITIONS \
|
||||
PROVIDE(kallsyms_addresses = .); \
|
||||
PROVIDE(kallsyms_offsets = .); \
|
||||
PROVIDE(kallsyms_names = .); \
|
||||
PROVIDE(kallsyms_num_syms = .); \
|
||||
PROVIDE(kallsyms_relative_base = .); \
|
||||
PROVIDE(kallsyms_token_table = .); \
|
||||
PROVIDE(kallsyms_token_index = .); \
|
||||
PROVIDE(kallsyms_markers = .); \
|
||||
PROVIDE(kallsyms_seqs_of_names = .);
|
||||
|
||||
/*
|
||||
* Read only Data
|
||||
*/
|
||||
#define RO_DATA(align) \
|
||||
. = ALIGN((align)); \
|
||||
PRELIMINARY_SYMBOL_DEFINITIONS \
|
||||
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
|
||||
__start_rodata = .; \
|
||||
*(.rodata) *(.rodata.*) \
|
||||
|
|
18
init/Kconfig
18
init/Kconfig
|
@ -1803,24 +1803,6 @@ config KALLSYMS_ABSOLUTE_PERCPU
|
|||
depends on KALLSYMS
|
||||
default X86_64 && SMP
|
||||
|
||||
config KALLSYMS_BASE_RELATIVE
|
||||
bool
|
||||
depends on KALLSYMS
|
||||
default y
|
||||
help
|
||||
Instead of emitting them as absolute values in the native word size,
|
||||
emit the symbol references in the kallsyms table as 32-bit entries,
|
||||
each containing a relative value in the range [base, base + U32_MAX]
|
||||
or, when KALLSYMS_ABSOLUTE_PERCPU is in effect, each containing either
|
||||
an absolute value in the range [0, S32_MAX] or a relative value in the
|
||||
range [base, base + S32_MAX], where base is the lowest relative symbol
|
||||
address encountered in the image.
|
||||
|
||||
On 64-bit builds, this reduces the size of the address table by 50%,
|
||||
but more importantly, it results in entries whose values are build
|
||||
time constants, and no relocation pass is required at runtime to fix
|
||||
up the entries based on the runtime load address of the kernel.
|
||||
|
||||
# end of the "standard kernel features (expert users)" menu
|
||||
|
||||
config ARCH_HAS_MEMBARRIER_CALLBACKS
|
||||
|
|
|
@ -52,7 +52,7 @@ CFLAGS_version.o := -include $(obj)/utsversion-tmp.h
|
|||
# Build version-timestamp.c with final UTS_VERSION
|
||||
#
|
||||
|
||||
include/generated/utsversion.h: build-version-auto = $(shell $(src)/build-version)
|
||||
include/generated/utsversion.h: build-version-auto = $(shell $(srctree)/scripts/build-version)
|
||||
include/generated/utsversion.h: build-timestamp-auto = $(shell LC_ALL=C date)
|
||||
include/generated/utsversion.h: FORCE
|
||||
$(call filechk,uts_version)
|
||||
|
|
|
@ -148,9 +148,6 @@ static unsigned int get_symbol_offset(unsigned long pos)
|
|||
|
||||
unsigned long kallsyms_sym_address(int idx)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
|
||||
return kallsyms_addresses[idx];
|
||||
|
||||
/* values are unsigned offsets if --absolute-percpu is not in effect */
|
||||
if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
|
||||
return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
|
||||
|
@ -325,7 +322,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
|
|||
unsigned long symbol_start = 0, symbol_end = 0;
|
||||
unsigned long i, low, high, mid;
|
||||
|
||||
/* Do a binary search on the sorted kallsyms_addresses array. */
|
||||
/* Do a binary search on the sorted kallsyms_offsets array. */
|
||||
low = 0;
|
||||
high = kallsyms_num_syms;
|
||||
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* These will be re-linked against their real values during the second link
|
||||
* stage. Preliminary values must be provided in the linker script using the
|
||||
* PROVIDE() directive so that the first link stage can complete successfully.
|
||||
*/
|
||||
extern const unsigned long kallsyms_addresses[];
|
||||
extern const int kallsyms_offsets[];
|
||||
extern const u8 kallsyms_names[];
|
||||
|
||||
|
|
|
@ -216,12 +216,8 @@ static int __init crash_save_vmcoreinfo_init(void)
|
|||
VMCOREINFO_SYMBOL(kallsyms_num_syms);
|
||||
VMCOREINFO_SYMBOL(kallsyms_token_table);
|
||||
VMCOREINFO_SYMBOL(kallsyms_token_index);
|
||||
#ifdef CONFIG_KALLSYMS_BASE_RELATIVE
|
||||
VMCOREINFO_SYMBOL(kallsyms_offsets);
|
||||
VMCOREINFO_SYMBOL(kallsyms_relative_base);
|
||||
#else
|
||||
VMCOREINFO_SYMBOL(kallsyms_addresses);
|
||||
#endif /* CONFIG_KALLSYMS_BASE_RELATIVE */
|
||||
#endif /* CONFIG_KALLSYMS */
|
||||
|
||||
arch_crash_save_vmcoreinfo();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -409,12 +409,16 @@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ;
|
|||
|
||||
DT_CHECK_CMD = $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA)
|
||||
|
||||
# NOTE:
|
||||
# Do not replace $(filter %.dtb %.dtbo, $^) with $(real-prereqs). When a single
|
||||
# DTB is turned into a multi-blob DTB, $^ will contain header file dependencies
|
||||
# recorded in the .*.cmd file.
|
||||
ifneq ($(CHECK_DTBS),)
|
||||
quiet_cmd_fdtoverlay = DTOVLCH $@
|
||||
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(real-prereqs) ; $(DT_CHECK_CMD) $@ || true
|
||||
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(filter %.dtb %.dtbo, $^) ; $(DT_CHECK_CMD) $@ || true
|
||||
else
|
||||
quiet_cmd_fdtoverlay = DTOVL $@
|
||||
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(real-prereqs)
|
||||
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(filter %.dtb %.dtbo, $^)
|
||||
endif
|
||||
|
||||
$(multi-dtb-y): FORCE
|
||||
|
@ -529,6 +533,7 @@ quiet_cmd_fit = FIT $@
|
|||
cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
|
||||
--name '$(UIMAGE_NAME)' \
|
||||
$(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
|
||||
$(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
|
||||
--compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
|
||||
|
||||
# XZ
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -127,6 +127,29 @@ static inline void list_del(struct list_head *entry)
|
|||
entry->prev = LIST_POISON2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -166,6 +189,17 @@ static inline int list_empty(const struct list_head *head)
|
|||
#define list_first_entry(ptr, type, member) \
|
||||
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
|
||||
|
@ -174,6 +208,14 @@ static inline int list_empty(const struct list_head *head)
|
|||
#define list_next_entry(pos, member) \
|
||||
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
|
||||
|
@ -194,6 +236,17 @@ static inline int list_empty(const struct list_head *head)
|
|||
!list_entry_is_head(pos, head, member); \
|
||||
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.
|
|
@ -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}" \
|
||||
|
|
|
@ -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");
|
||||
|
||||
/*
|
||||
* 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");
|
||||
|
||||
/*
|
||||
* 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++) {
|
||||
expand_symbol(table[i]->sym, table[i]->len, buf);
|
||||
strcpy((char *)table[i]->sym, buf);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* count entries in choice block */
|
||||
cnt = 0;
|
||||
expr_list_for_each_sym(prop->expr, e, sym)
|
||||
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;
|
||||
}
|
||||
sym->flags |= SYMBOL_DEF_USER;
|
||||
/* clear VALID to get value calculated */
|
||||
sym->flags &= ~SYMBOL_VALID;
|
||||
if (sym && !sym_has_value(sym))
|
||||
cnt++;
|
||||
}
|
||||
csym->flags |= SYMBOL_DEF_USER;
|
||||
/* clear VALID to get value calculated */
|
||||
csym->flags &= ~SYMBOL_VALID;
|
||||
|
||||
return true;
|
||||
while (cnt > 0) {
|
||||
x = rand() % cnt;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
cnt--;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
menu_for_each_entry(menu) {
|
||||
struct symbol *sym = menu->sym;
|
||||
tristate val;
|
||||
|
||||
if (!sym || !menu->prompt || sym_has_value(sym) ||
|
||||
(sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||
|
||||
sym_is_choice_value(sym))
|
||||
continue;
|
||||
|
||||
if (sym_is_choice(sym)) {
|
||||
if (mode == def_random)
|
||||
randomize_choice_values(menu);
|
||||
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;
|
||||
}
|
||||
|
||||
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->def[S_DEF_USER].tri = val;
|
||||
sym->flags |= SYMBOL_DEF_USER;
|
||||
}
|
||||
|
||||
sym_clear_all_valid();
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
for_all_symbols(csym) {
|
||||
if (sym_has_value(csym) || !sym_is_choice(csym))
|
||||
continue;
|
||||
|
||||
sym_calc_value(csym);
|
||||
if (mode == def_random)
|
||||
has_changed |= randomize_choice_values(csym);
|
||||
else {
|
||||
set_all_choice_values(csym);
|
||||
has_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return has_changed;
|
||||
}
|
||||
|
||||
static void conf_rewrite_tristates(tristate old_val, tristate new_val)
|
||||
|
@ -448,39 +422,15 @@ static int conf_sym(struct menu *menu)
|
|||
|
||||
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);
|
||||
|
|
|
@ -382,10 +382,7 @@ int conf_read_simple(const char *name, int def)
|
|||
|
||||
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 @@ int conf_read_simple(const char *name, int def)
|
|||
}
|
||||
|
||||
while (getline_stripped(&line, &line_asize, in) != -1) {
|
||||
struct menu *choice;
|
||||
|
||||
conf_lineno++;
|
||||
|
||||
if (!line[0]) /* blank line */
|
||||
|
@ -460,25 +459,14 @@ int conf_read_simple(const char *name, int def)
|
|||
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 @@ int conf_read_simple(const char *name, int def)
|
|||
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;
|
||||
if (!sym || sym_is_choice(sym))
|
||||
continue;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
cflags=$1
|
||||
libs=$2
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#ifndef INTERNAL_H
|
||||
#define INTERNAL_H
|
||||
|
||||
#include "hashtable.h"
|
||||
#include <hashtable.h>
|
||||
|
||||
#define SYMBOL_HASHSIZE (1U << 14)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
cflags=$1
|
||||
libs=$2
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <list_types.h>
|
||||
|
||||
struct search_data {
|
||||
struct list_head *head;
|
||||
struct menu *target;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
cflags=$1
|
||||
libs=$2
|
||||
|
||||
|
|
|
@ -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 '?':
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
cflags=$1
|
||||
libs=$2
|
||||
bin=$3
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
struct symbol *res = NULL;
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
return def_sym;
|
||||
/*
|
||||
* 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 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->visible > sym->rev_dep.tri;
|
||||
return !sym_is_choice(sym) && sym->visible > sym->rev_dep.tri;
|
||||
}
|
||||
|
||||
bool sym_is_choice_value(const struct symbol *sym)
|
||||
{
|
||||
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;
|
||||
type = stack->prop ? stack->prop->type : P_UNKNOWN;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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,
|
||||
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>");
|
||||
} else if (sym_is_choice_value(sym)) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
|
||||
menu->filename, menu->lineno,
|
||||
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 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
|
|||
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 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
|
|||
|
||||
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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_MODULES is not set
|
|
@ -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?]:
|
|
@ -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
|
|
@ -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')
|
|
@ -1,2 +0,0 @@
|
|||
CONFIG_CHOICE0=m
|
||||
CONFIG_CHOICE1=m
|
|
@ -1,3 +0,0 @@
|
|||
CONFIG_MODULES=y
|
||||
CONFIG_DEP=m
|
||||
CONFIG_CHOICE0=y
|
|
@ -1,4 +0,0 @@
|
|||
Tristate Choice [M/y/?] y
|
||||
Tristate Choice
|
||||
> 1. Choice 0 (CHOICE0)
|
||||
choice[1]: 1
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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')
|
|
@ -1 +0,0 @@
|
|||
CONFIG_CHOICE_VAL0=y
|
|
@ -1,4 +0,0 @@
|
|||
CONFIG_MODULES=y
|
||||
CONFIG_CHOICE_VAL0=y
|
||||
# CONFIG_CHOIVE_VAL1 is not set
|
||||
CONFIG_DUMMY=y
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
mksysmap "${1}" "${1}.syms"
|
||||
kallsyms "${1}.syms" "${1}.kallsyms"
|
||||
|
||||
vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
|
||||
mksysmap ${kallsyms_vmlinux} ${kallsyms_vmlinux}.syms
|
||||
kallsyms ${kallsyms_vmlinux}.syms ${kallsyms_S}
|
||||
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -20,6 +20,9 @@
|
|||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <hashtable.h>
|
||||
#include <list.h>
|
||||
#include "modpost.h"
|
||||
#include "../../include/linux/license.h"
|
||||
|
||||
|
@ -199,13 +202,8 @@ static struct module *new_module(const char *name, size_t namelen)
|
|||
return mod;
|
||||
}
|
||||
|
||||
/* A hash of all exported symbols,
|
||||
* struct symbol is also used for lists of unresolved symbols */
|
||||
|
||||
#define SYMBOL_HASH_SIZE 1024
|
||||
|
||||
struct symbol {
|
||||
struct symbol *next;
|
||||
struct hlist_node hnode;/* link to hash table */
|
||||
struct list_head list; /* link to module::exported_symbols or module::unresolved_symbols */
|
||||
struct module *module;
|
||||
char *namespace;
|
||||
|
@ -218,7 +216,7 @@ struct symbol {
|
|||
char name[];
|
||||
};
|
||||
|
||||
static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
|
||||
static HASHTABLE_DEFINE(symbol_hashtable, 1U << 10);
|
||||
|
||||
/* This is based on the hash algorithm from gdbm, via tdb */
|
||||
static inline unsigned int tdb_hash(const char *name)
|
||||
|
@ -250,11 +248,7 @@ static struct symbol *alloc_symbol(const char *name)
|
|||
/* For the hash of exported symbols */
|
||||
static void hash_add_symbol(struct symbol *sym)
|
||||
{
|
||||
unsigned int hash;
|
||||
|
||||
hash = tdb_hash(sym->name) % SYMBOL_HASH_SIZE;
|
||||
sym->next = symbolhash[hash];
|
||||
symbolhash[hash] = sym;
|
||||
hash_add(symbol_hashtable, &sym->hnode, tdb_hash(sym->name));
|
||||
}
|
||||
|
||||
static void sym_add_unresolved(const char *name, struct module *mod, bool weak)
|
||||
|
@ -275,7 +269,7 @@ static struct symbol *sym_find_with_module(const char *name, struct module *mod)
|
|||
if (name[0] == '.')
|
||||
name++;
|
||||
|
||||
for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) {
|
||||
hash_for_each_possible(symbol_hashtable, s, hnode, tdb_hash(name)) {
|
||||
if (strcmp(s->name, name) == 0 && (!mod || s->module == mod))
|
||||
return s;
|
||||
}
|
||||
|
@ -954,17 +948,6 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
|
|||
match(fromsym, PATTERNS("*_ops", "*_probe", "*_console")))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* symbols in data sections must not refer to .exit.*, but there are
|
||||
* quite a few offenders, so hide these unless for W=1 builds until
|
||||
* these are fixed.
|
||||
*/
|
||||
if (!extra_warn &&
|
||||
match(fromsec, PATTERNS(DATA_SECTIONS)) &&
|
||||
match(tosec, PATTERNS(ALL_EXIT_SECTIONS)) &&
|
||||
match(fromsym, PATTERNS("*driver")))
|
||||
return 0;
|
||||
|
||||
/* Check for pattern 3 */
|
||||
if (strstarts(fromsec, ".head.text") &&
|
||||
match(tosec, PATTERNS(ALL_INIT_SECTIONS)))
|
||||
|
@ -1168,40 +1151,6 @@ static Elf_Addr addend_386_rel(uint32_t *location, unsigned int r_type)
|
|||
return (Elf_Addr)(-1);
|
||||
}
|
||||
|
||||
#ifndef R_ARM_CALL
|
||||
#define R_ARM_CALL 28
|
||||
#endif
|
||||
#ifndef R_ARM_JUMP24
|
||||
#define R_ARM_JUMP24 29
|
||||
#endif
|
||||
|
||||
#ifndef R_ARM_THM_CALL
|
||||
#define R_ARM_THM_CALL 10
|
||||
#endif
|
||||
#ifndef R_ARM_THM_JUMP24
|
||||
#define R_ARM_THM_JUMP24 30
|
||||
#endif
|
||||
|
||||
#ifndef R_ARM_MOVW_ABS_NC
|
||||
#define R_ARM_MOVW_ABS_NC 43
|
||||
#endif
|
||||
|
||||
#ifndef R_ARM_MOVT_ABS
|
||||
#define R_ARM_MOVT_ABS 44
|
||||
#endif
|
||||
|
||||
#ifndef R_ARM_THM_MOVW_ABS_NC
|
||||
#define R_ARM_THM_MOVW_ABS_NC 47
|
||||
#endif
|
||||
|
||||
#ifndef R_ARM_THM_MOVT_ABS
|
||||
#define R_ARM_THM_MOVT_ABS 48
|
||||
#endif
|
||||
|
||||
#ifndef R_ARM_THM_JUMP19
|
||||
#define R_ARM_THM_JUMP19 51
|
||||
#endif
|
||||
|
||||
static int32_t sign_extend32(int32_t value, int index)
|
||||
{
|
||||
uint8_t shift = 31 - index;
|
||||
|
@ -1262,7 +1211,7 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
|
|||
((lower & 0x07ff) << 1),
|
||||
20);
|
||||
return offset + sym->st_value + 4;
|
||||
case R_ARM_THM_CALL:
|
||||
case R_ARM_THM_PC22:
|
||||
case R_ARM_THM_JUMP24:
|
||||
/*
|
||||
* Encoding T4:
|
||||
|
|
|
@ -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 */
|
||||
|
|
108
scripts/package/PKGBUILD
Normal file
108
scripts/package/PKGBUILD
Normal file
|
@ -0,0 +1,108 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Maintainer: Thomas Weißschuh <linux@weissschuh.net>
|
||||
# Contributor: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
|
||||
|
||||
pkgbase=${PACMAN_PKGBASE:-linux-upstream}
|
||||
pkgname=("${pkgbase}" "${pkgbase}-api-headers")
|
||||
if grep -q CONFIG_MODULES=y include/config/auto.conf; then
|
||||
pkgname+=("${pkgbase}-headers")
|
||||
fi
|
||||
pkgver="${KERNELRELEASE//-/_}"
|
||||
# The PKGBUILD is evaluated multiple times.
|
||||
# Running scripts/build-version from here would introduce inconsistencies.
|
||||
pkgrel="${KBUILD_REVISION}"
|
||||
pkgdesc='Upstream Linux'
|
||||
url='https://www.kernel.org/'
|
||||
# Enable flexible cross-compilation
|
||||
arch=(${CARCH})
|
||||
license=(GPL-2.0-only)
|
||||
makedepends=(
|
||||
bc
|
||||
bison
|
||||
cpio
|
||||
flex
|
||||
gettext
|
||||
kmod
|
||||
libelf
|
||||
openssl
|
||||
pahole
|
||||
perl
|
||||
python
|
||||
rsync
|
||||
tar
|
||||
)
|
||||
options=(!debug !strip !buildflags !makeflags)
|
||||
|
||||
build() {
|
||||
# MAKEFLAGS from makepkg.conf override the ones inherited from kbuild.
|
||||
# Bypass this override with a custom variable.
|
||||
export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
|
||||
cd "${objtree}"
|
||||
|
||||
${MAKE} KERNELRELEASE="${KERNELRELEASE}" KBUILD_BUILD_VERSION="${pkgrel}"
|
||||
}
|
||||
|
||||
_package() {
|
||||
pkgdesc="The ${pkgdesc} kernel and modules"
|
||||
|
||||
export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
|
||||
cd "${objtree}"
|
||||
local modulesdir="${pkgdir}/usr/${MODLIB}"
|
||||
|
||||
echo "Installing boot image..."
|
||||
# systemd expects to find the kernel here to allow hibernation
|
||||
# https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344
|
||||
install -Dm644 "$(${MAKE} -s image_name)" "${modulesdir}/vmlinuz"
|
||||
|
||||
# Used by mkinitcpio to name the kernel
|
||||
echo "${pkgbase}" > "${modulesdir}/pkgbase"
|
||||
|
||||
echo "Installing modules..."
|
||||
${MAKE} INSTALL_MOD_PATH="${pkgdir}/usr" INSTALL_MOD_STRIP=1 \
|
||||
DEPMOD=true modules_install
|
||||
|
||||
if [ -d "${srctree}/arch/${SRCARCH}/boot/dts" ]; then
|
||||
echo "Installing dtbs..."
|
||||
${MAKE} INSTALL_DTBS_PATH="${modulesdir}/dtb" dtbs_install
|
||||
fi
|
||||
|
||||
# remove build link, will be part of -headers package
|
||||
rm -f "${modulesdir}/build"
|
||||
}
|
||||
|
||||
_package-headers() {
|
||||
pkgdesc="Headers and scripts for building modules for the ${pkgdesc} kernel"
|
||||
|
||||
export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
|
||||
cd "${objtree}"
|
||||
local builddir="${pkgdir}/usr/${MODLIB}/build"
|
||||
|
||||
echo "Installing build files..."
|
||||
"${srctree}/scripts/package/install-extmod-build" "${builddir}"
|
||||
|
||||
echo "Installing System.map and config..."
|
||||
cp System.map "${builddir}/System.map"
|
||||
cp .config "${builddir}/.config"
|
||||
|
||||
echo "Adding symlink..."
|
||||
mkdir -p "${pkgdir}/usr/src"
|
||||
ln -sr "${builddir}" "${pkgdir}/usr/src/${pkgbase}"
|
||||
}
|
||||
|
||||
_package-api-headers() {
|
||||
pkgdesc="Kernel headers sanitized for use in userspace"
|
||||
provides=(linux-api-headers)
|
||||
conflicts=(linux-api-headers)
|
||||
|
||||
export MAKEFLAGS="${KBUILD_MAKEFLAGS}"
|
||||
cd "${objtree}"
|
||||
|
||||
${MAKE} headers_install INSTALL_HDR_PATH="${pkgdir}/usr"
|
||||
}
|
||||
|
||||
for _p in "${pkgname[@]}"; do
|
||||
eval "package_$_p() {
|
||||
$(declare -f "_package${_p#$pkgbase}")
|
||||
_package${_p#$pkgbase}
|
||||
}"
|
||||
done
|
|
@ -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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# Wichert Akkerman <wichert@wiggy.net>.
|
||||
#
|
||||
|
||||
set -e
|
||||
set -eu
|
||||
|
||||
#
|
||||
# Some variables and settings used throughout the script
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
set -eu
|
||||
|
||||
diff_patch=$1
|
||||
|
||||
mkdir -p "$(dirname "${diff_patch}")"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
# Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
|
||||
#
|
||||
|
||||
set -eu
|
||||
|
||||
output=$1
|
||||
|
||||
mkdir -p "$(dirname "${output}")"
|
||||
|
@ -24,7 +26,30 @@ fi
|
|||
cat<<EOF
|
||||
%define ARCH ${ARCH}
|
||||
%define KERNELRELEASE ${KERNELRELEASE}
|
||||
%define pkg_release $("${srctree}/init/build-version")
|
||||
%define pkg_release $("${srctree}/scripts/build-version")
|
||||
EOF
|
||||
|
||||
cat "${srctree}/scripts/package/kernel.spec"
|
||||
|
||||
# collect the user's name and email address for the changelog entry
|
||||
if [ "$(command -v git)" ]; then
|
||||
name=$(git config user.name) || true
|
||||
email=$(git config user.email) || true
|
||||
fi
|
||||
|
||||
if [ ! "${name:+set}" ]; then
|
||||
name=${KBUILD_BUILD_USER:-$(id -nu)}
|
||||
fi
|
||||
|
||||
if [ ! "${email:+set}" ]; then
|
||||
buildhost=${KBUILD_BUILD_HOST:-$(hostname -f 2>/dev/null || hostname)}
|
||||
builduser=${KBUILD_BUILD_USER:-$(id -nu)}
|
||||
email="${builduser}@${buildhost}"
|
||||
fi
|
||||
|
||||
cat << EOF
|
||||
|
||||
%changelog
|
||||
* $(LC_ALL=C; date +'%a %b %d %Y') ${name} <${email}>
|
||||
- Custom built Linux kernel.
|
||||
EOF
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -26,7 +26,6 @@ static bool is_ignored_symbol(const char *name, char type)
|
|||
* when --all-symbols is specified so exclude them to get a
|
||||
* stable symbol list.
|
||||
*/
|
||||
"kallsyms_addresses",
|
||||
"kallsyms_offsets",
|
||||
"kallsyms_relative_base",
|
||||
"kallsyms_num_syms",
|
||||
|
|
|
@ -62,8 +62,8 @@ $(deps_initramfs): ;
|
|||
quiet_cmd_initfs = GEN $@
|
||||
cmd_initfs = \
|
||||
$(CONFIG_SHELL) $< -o $@ -l $(obj)/.initramfs_data.cpio.d \
|
||||
$(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
|
||||
$(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
|
||||
$(addprefix -u , $(CONFIG_INITRAMFS_ROOT_UID)) \
|
||||
$(addprefix -g , $(CONFIG_INITRAMFS_ROOT_GID)) \
|
||||
$(if $(KBUILD_BUILD_TIMESTAMP), -d "$(KBUILD_BUILD_TIMESTAMP)") \
|
||||
$(ramfs-input)
|
||||
|
||||
|
|
Loading…
Reference in a new issue