summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.build67
-rw-r--r--scripts/Makefile.dtbinst3
-rw-r--r--scripts/Makefile.lib23
-rw-r--r--scripts/Makefile.modfinal26
-rw-r--r--scripts/Makefile.modpost25
-rwxr-xr-xscripts/checkpatch.pl12
-rw-r--r--scripts/coccinelle/free/put_device.cocci1
-rw-r--r--scripts/dtc/.gitignore1
-rw-r--r--scripts/dtc/Makefile9
-rw-r--r--scripts/dtc/data.c6
-rw-r--r--scripts/dtc/dtc.c4
-rw-r--r--scripts/dtc/dtc.h8
-rw-r--r--scripts/dtc/fdtdump.c163
-rw-r--r--scripts/dtc/fdtoverlay.c208
-rw-r--r--scripts/dtc/flattree.c8
-rw-r--r--scripts/dtc/libfdt/fdt.c4
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c20
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c4
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c2
-rw-r--r--scripts/dtc/libfdt/libfdt.h126
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h19
-rw-r--r--scripts/dtc/livetree.c2
-rw-r--r--scripts/dtc/srcpos.c2
-rwxr-xr-xscripts/dtc/update-dtc-source.sh3
-rw-r--r--scripts/dtc/version_gen.h2
-rw-r--r--scripts/dtc/yamltree.c6
-rwxr-xr-xscripts/gen_autoksyms.sh3
-rwxr-xr-xscripts/generate_initcall_order.pl270
-rwxr-xr-xscripts/kernel-doc63
-rwxr-xr-xscripts/link-vmlinux.sh98
-rw-r--r--scripts/lto-used-symbollist.txt5
-rw-r--r--scripts/mod/Makefile1
-rw-r--r--scripts/mod/devicetable-offsets.c12
-rw-r--r--scripts/mod/file2alias.c36
-rw-r--r--scripts/mod/modpost.c66
-rw-r--r--scripts/mod/modpost.h12
-rw-r--r--scripts/mod/sumversion.c6
-rw-r--r--scripts/module.lds.S30
-rwxr-xr-xscripts/recordmcount.pl6
-rwxr-xr-xscripts/spdxcheck.py2
-rw-r--r--scripts/spelling.txt30
-rwxr-xr-xscripts/sphinx-pre-install4
-rwxr-xr-xscripts/ver_linux12
44 files changed, 1028 insertions, 383 deletions
diff --git a/scripts/Makefile b/scripts/Makefile
index 9de3c03b94aa..c36106bce80e 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -17,6 +17,7 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
+HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS)
HOSTLDLIBS_sign-file = $(CRYPTO_LIBS)
HOSTCFLAGS_extract-cert.o = $(CRYPTO_CFLAGS)
HOSTLDLIBS_extract-cert = $(CRYPTO_LIBS)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 3a07c46caa3e..1b6094a13034 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -110,7 +110,7 @@ endif
# ---------------------------------------------------------------------------
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
- cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) -fverbose-asm -S -o $@ $<
+ cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS) $(CC_FLAGS_LTO), $(c_flags)) -fverbose-asm -S -o $@ $<
$(obj)/%.s: $(src)/%.c FORCE
$(call if_changed_dep,cc_s_c)
@@ -165,6 +165,15 @@ ifdef CONFIG_MODVERSIONS
# the actual value of the checksum generated by genksyms
# o remove .tmp_<file>.o to <file>.o
+ifdef CONFIG_LTO_CLANG
+# Generate .o.symversions files for each .o with exported symbols, and link these
+# to the kernel and/or modules at the end.
+cmd_modversions_c = \
+ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
+ $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
+ > $@.symversions; \
+ fi;
+else
cmd_modversions_c = \
if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
@@ -176,9 +185,9 @@ cmd_modversions_c = \
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
fi
endif
+endif
-ifdef CONFIG_FTRACE_MCOUNT_RECORD
-ifndef CC_USING_RECORD_MCOUNT
+ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
ifdef BUILD_C_RECORDMCOUNT
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
@@ -205,31 +214,14 @@ recordmcount_source := $(srctree)/scripts/recordmcount.pl
endif # BUILD_C_RECORDMCOUNT
cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
$(sub_cmd_record_mcount))
-endif # CC_USING_RECORD_MCOUNT
-endif # CONFIG_FTRACE_MCOUNT_RECORD
+endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
ifdef CONFIG_STACK_VALIDATION
+ifndef CONFIG_LTO_CLANG
ifneq ($(SKIP_STACK_VALIDATION),1)
__objtool_obj := $(objtree)/tools/objtool/objtool
-objtool_args = $(if $(CONFIG_UNWINDER_ORC),orc generate,check)
-
-objtool_args += $(if $(part-of-module), --module,)
-
-ifndef CONFIG_FRAME_POINTER
-objtool_args += --no-fp
-endif
-ifdef CONFIG_GCOV_KERNEL
-objtool_args += --no-unreachable
-endif
-ifdef CONFIG_RETPOLINE
- objtool_args += --retpoline
-endif
-ifdef CONFIG_X86_SMAP
- objtool_args += --uaccess
-endif
-
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
@@ -241,6 +233,7 @@ objtool_obj = $(if $(patsubst y%,, \
$(__objtool_obj))
endif # SKIP_STACK_VALIDATION
+endif # CONFIG_LTO_CLANG
endif # CONFIG_STACK_VALIDATION
# Rebuild all objects when objtool changes, or is enabled/disabled.
@@ -387,6 +380,18 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+# combine symversions for later processing
+quiet_cmd_update_lto_symversions = SYMVER $@
+ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
+ cmd_update_lto_symversions = \
+ rm -f $@.symversions \
+ $(foreach n, $(filter-out FORCE,$^), \
+ $(if $(wildcard $(n).symversions), \
+ ; cat $(n).symversions >> $@.symversions))
+else
+ cmd_update_lto_symversions = echo >/dev/null
+endif
+
#
# Rule to compile a set of .o files into one .a file (without symbol table)
#
@@ -394,8 +399,11 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
quiet_cmd_ar_builtin = AR $@
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
+quiet_cmd_ar_and_symver = AR $@
+ cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin)
+
$(obj)/built-in.a: $(real-obj-y) FORCE
- $(call if_changed,ar_builtin)
+ $(call if_changed,ar_and_symver)
#
# Rule to create modules.order file
@@ -415,15 +423,26 @@ $(obj)/modules.order: $(obj-m) FORCE
#
# Rule to compile a set of .o files into one .a file (with symbol table)
#
+quiet_cmd_ar_lib = AR $@
+ cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar)
+
$(obj)/lib.a: $(lib-y) FORCE
- $(call if_changed,ar)
+ $(call if_changed,ar_lib)
# NOTE:
# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
# module is turned into a multi object module, $^ will contain header file
# dependencies recorded in the .*.cmd file.
+ifdef CONFIG_LTO_CLANG
+quiet_cmd_link_multi-m = AR [M] $@
+cmd_link_multi-m = \
+ $(cmd_update_lto_symversions); \
+ rm -f $@; \
+ $(AR) cDPrsT $@ $(filter %.o,$^)
+else
quiet_cmd_link_multi-m = LD [M] $@
cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
+endif
$(multi-used-m): FORCE
$(call if_changed,link_multi-m)
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
index 50d580d77ae9..ba01f5ba2517 100644
--- a/scripts/Makefile.dtbinst
+++ b/scripts/Makefile.dtbinst
@@ -29,6 +29,9 @@ quiet_cmd_dtb_install = INSTALL $@
$(dst)/%.dtb: $(obj)/%.dtb
$(call cmd,dtb_install)
+$(dst)/%.dtbo: $(obj)/%.dtbo
+ $(call cmd,dtb_install)
+
PHONY += $(subdirs)
$(subdirs):
$(Q)$(MAKE) $(dtbinst)=$@ dst=$(patsubst $(obj)/%,$(dst)/%,$@)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index d5ec3864b318..eee59184de64 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -78,7 +78,9 @@ always-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
ifneq ($(CHECK_DTBS),)
always-y += $(patsubst %.dtb,%.dt.yaml, $(dtb-y))
+always-y += $(patsubst %.dtbo,%.dt.yaml, $(dtb-y))
always-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtb,%.dt.yaml, $(dtb-))
+always-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtbo,%.dt.yaml, $(dtb-))
endif
# Add subdir path
@@ -109,9 +111,11 @@ target-stem = $(basename $(patsubst $(obj)/%,%,$@))
# These flags are needed for modversions and compiling, so we define them here
# $(modname_flags) defines KBUILD_MODNAME as the name of the module it will
# end up in (or would, if it gets compiled in)
-name-fix = $(call stringify,$(subst $(comma),_,$(subst -,_,$1)))
+name-fix-token = $(subst $(comma),_,$(subst -,_,$1))
+name-fix = $(call stringify,$(call name-fix-token,$1))
basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
-modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))
+modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname)) \
+ -D__KBUILD_MODNAME=kmod_$(call name-fix-token,$(modname))
modfile_flags = -DKBUILD_MODFILE=$(call stringify,$(modfile))
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(target-stem).o), \
@@ -210,6 +214,18 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \
$(addprefix -I,$(DTC_INCLUDE)) \
-undef -D__DTS__
+# Objtool arguments are also needed for modfinal with LTO, so we define
+# then here to avoid duplication.
+objtool_args = \
+ $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
+ $(if $(part-of-module), --module,) \
+ $(if $(CONFIG_FRAME_POINTER),, --no-fp) \
+ $(if $(or $(CONFIG_GCOV_KERNEL),$(CONFIG_LTO_CLANG)), \
+ --no-unreachable,) \
+ $(if $(CONFIG_RETPOLINE), --retpoline,) \
+ $(if $(CONFIG_X86_SMAP), --uaccess,) \
+ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount,)
+
# Useful for describing the dependency of composite objects
# Usage:
# $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
@@ -319,6 +335,9 @@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ;
$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
$(call if_changed_dep,dtc)
+$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE
+ $(call if_changed_dep,dtc)
+
DT_CHECKER ?= dt-validate
DT_BINDING_DIR := Documentation/devicetree/bindings
# DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index d49ec001825d..735e11e9041b 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -9,7 +9,7 @@ __modfinal:
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-# for c_flags
+# for c_flags and objtool_args
include $(srctree)/scripts/Makefile.lib
# find all modules listed in modules.order
@@ -30,8 +30,27 @@ quiet_cmd_cc_o_c = CC [M] $@
ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
+ifdef CONFIG_LTO_CLANG
+# With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
+# avoid a second slow LTO link
+prelink-ext := .lto
+
+# ELF processing was skipped earlier because we didn't have native code,
+# so let's now process the prelinked binary before we link the module.
+
+ifdef CONFIG_STACK_VALIDATION
+ifneq ($(SKIP_STACK_VALIDATION),1)
+cmd_ld_ko_o += \
+ $(objtree)/tools/objtool/objtool $(objtool_args) \
+ $(@:.ko=$(prelink-ext).o);
+
+endif # SKIP_STACK_VALIDATION
+endif # CONFIG_STACK_VALIDATION
+
+endif # CONFIG_LTO_CLANG
+
quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = \
+ cmd_ld_ko_o += \
$(LD) -r $(KBUILD_LDFLAGS) \
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-T scripts/module.lds -o $@ $(filter %.o, $^); \
@@ -53,8 +72,9 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
$(cmd); \
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
+
# Re-generate module BTFs if either module's .ko or vmlinux changed
-$(modules): %.ko: %.o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
+$(modules): %.ko: %$(prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
+$(call if_changed_except,ld_ko_o,vmlinux)
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index f54b6ac37ac2..066beffca09a 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -43,6 +43,9 @@ __modpost:
include include/config/auto.conf
include scripts/Kbuild.include
+# for ld_flags
+include scripts/Makefile.lib
+
MODPOST = scripts/mod/modpost \
$(if $(CONFIG_MODVERSIONS),-m) \
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
@@ -102,12 +105,30 @@ $(input-symdump):
@echo >&2 'WARNING: Symbol version dump "$@" is missing.'
@echo >&2 ' Modules may not have dependencies or modversions.'
+ifdef CONFIG_LTO_CLANG
+# With CONFIG_LTO_CLANG, .o files might be LLVM bitcode, so we need to run
+# LTO to compile them into native code before running modpost
+prelink-ext := .lto
+
+quiet_cmd_cc_lto_link_modules = LTO [M] $@
+cmd_cc_lto_link_modules = \
+ $(LD) $(ld_flags) -r -o $@ \
+ $(shell [ -s $(@:.lto.o=.o.symversions) ] && \
+ echo -T $(@:.lto.o=.o.symversions)) \
+ --whole-archive $^
+
+%.lto.o: %.o
+ $(call if_changed,cc_lto_link_modules)
+endif
+
+modules := $(sort $(shell cat $(MODORDER)))
+
# Read out modules.order to pass in modpost.
# Otherwise, allmodconfig would fail with "Argument list too long".
quiet_cmd_modpost = MODPOST $@
- cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T -
+ cmd_modpost = sed 's/\.ko$$/$(prelink-ext)\.o/' $< | $(MODPOST) -T -
-$(output-symdump): $(MODORDER) $(input-symdump) FORCE
+$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(prelink-ext).o) FORCE
$(call if_changed,modpost)
targets += $(output-symdump)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 1afe3af1cc09..ca4201753d5e 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -4283,8 +4283,7 @@ sub process {
if (defined $realline_next &&
exists $lines[$realline_next - 1] &&
!defined $suppress_export{$realline_next} &&
- ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
- $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
# Handle definitions which produce identifiers with
# a prefix:
# XXX(foo);
@@ -4311,8 +4310,7 @@ sub process {
}
if (!defined $suppress_export{$linenr} &&
$prevline =~ /^.\s*$/ &&
- ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
- $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ ($line =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
#print "FOO B <$lines[$linenr - 1]>\n";
$suppress_export{$linenr} = 2;
}
@@ -7062,12 +7060,6 @@ sub process {
}
}
-# check for mutex_trylock_recursive usage
- if ($line =~ /mutex_trylock_recursive/) {
- ERROR("LOCKING",
- "recursive locking is bad, do not use this ever.\n" . $herecurr);
- }
-
# check for lockdep_set_novalidate_class
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
diff --git a/scripts/coccinelle/free/put_device.cocci b/scripts/coccinelle/free/put_device.cocci
index 120921366e84..f09f1e79bfa6 100644
--- a/scripts/coccinelle/free/put_device.cocci
+++ b/scripts/coccinelle/free/put_device.cocci
@@ -21,7 +21,6 @@ id = of_find_device_by_node@p1(x)
if (id == NULL || ...) { ... return ...; }
... when != put_device(&id->dev)
when != platform_device_put(id)
- when != of_dev_put(id)
when != if (id) { ... put_device(&id->dev) ... }
when != e1 = (T)id
when != e1 = (T)(&id->dev)
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
index b814e6076bdb..8a8b62bf3d3c 100644
--- a/scripts/dtc/.gitignore
+++ b/scripts/dtc/.gitignore
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
dtc
+fdtoverlay
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 4852bf44e913..95aaf7431bff 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -1,13 +1,20 @@
# SPDX-License-Identifier: GPL-2.0
# scripts/dtc makefile
-hostprogs-always-$(CONFIG_DTC) += dtc
+# *** Also keep .gitignore in sync when changing ***
+hostprogs-always-$(CONFIG_DTC) += dtc fdtoverlay
hostprogs-always-$(CHECK_DT_BINDING) += dtc
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
srcpos.o checks.o util.o
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+# The upstream project builds libfdt as a separate library. We are choosing to
+# instead directly link the libfdt object files into fdtoverlay.
+libfdt-objs := fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o fdt_empty_tree.o fdt_addresses.o fdt_overlay.o
+libfdt = $(addprefix libfdt/,$(libfdt-objs))
+fdtoverlay-objs := $(libfdt) fdtoverlay.o util.o
+
# Source files need to get at the userspace version of libfdt_env.h to compile
HOST_EXTRACFLAGS += -I $(srctree)/$(src)/libfdt
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index 0a43b6de3264..14734233ad8b 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -21,10 +21,10 @@ void data_free(struct data d)
free(d.val);
}
-struct data data_grow_for(struct data d, int xlen)
+struct data data_grow_for(struct data d, unsigned int xlen)
{
struct data nd;
- int newsize;
+ unsigned int newsize;
if (xlen == 0)
return d;
@@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
- if (maxlen == -1)
+ if (maxlen == (size_t)-1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index bdb3f5945699..838c5df96c00 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -122,6 +122,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
+ if (!strcasecmp(s, ".dtbo"))
+ return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@@ -357,6 +359,8 @@ int main(int argc, char *argv[])
#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
+ } else if (streq(outform, "dtbo")) {
+ dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
dt_to_asm(outf, dti, outversion);
} else if (streq(outform, "null")) {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index a08f4159cd03..d3e82fb8e3db 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -105,13 +105,13 @@ extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
- int offset;
+ unsigned int offset;
char *ref;
struct marker *next;
};
struct data {
- int len;
+ unsigned int len;
char *val;
struct marker *markers;
};
@@ -129,7 +129,7 @@ size_t type_marker_length(struct marker *m);
void data_free(struct data d);
-struct data data_grow_for(struct data d, int xlen);
+struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@@ -253,7 +253,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
-cell_t propval_cell_n(struct property *prop, int n);
+cell_t propval_cell_n(struct property *prop, unsigned int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
deleted file mode 100644
index 7d460a50b513..000000000000
--- a/scripts/dtc/fdtdump.c
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <fdt.h>
-#include <libfdt_env.h>
-
-#include "util.h"
-
-#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
-#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
-#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
-
-static void print_data(const char *data, int len)
-{
- int i;
- const char *p = data;
-
- /* no data, don't print */
- if (len == 0)
- return;
-
- if (util_is_printable_string(data, len)) {
- printf(" = \"%s\"", (const char *)data);
- } else if ((len % 4) == 0) {
- printf(" = <");
- for (i = 0; i < len; i += 4)
- printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
- i < (len - 4) ? " " : "");
- printf(">");
- } else {
- printf(" = [");
- for (i = 0; i < len; i++)
- printf("%02x%s", *p++, i < len - 1 ? " " : "");
- printf("]");
- }
-}
-
-static void dump_blob(void *blob)
-{
- struct fdt_header *bph = blob;
- uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
- uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
- uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
- struct fdt_reserve_entry *p_rsvmap =
- (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
- const char *p_struct = (const char *)blob + off_dt;
- const char *p_strings = (const char *)blob + off_str;
- uint32_t version = fdt32_to_cpu(bph->version);
- uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
- uint32_t tag;
- const char *p, *s, *t;
- int depth, sz, shift;
- int i;
- uint64_t addr, size;
-
- depth = 0;
- shift = 4;
-
- printf("/dts-v1/;\n");
- printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
- printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
- printf("// off_dt_struct:\t0x%x\n", off_dt);
- printf("// off_dt_strings:\t0x%x\n", off_str);
- printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
- printf("// version:\t\t%d\n", version);
- printf("// last_comp_version:\t%d\n",
- fdt32_to_cpu(bph->last_comp_version));
- if (version >= 2)
- printf("// boot_cpuid_phys:\t0x%x\n",
- fdt32_to_cpu(bph->boot_cpuid_phys));
-
- if (version >= 3)
- printf("// size_dt_strings:\t0x%x\n",
- fdt32_to_cpu(bph->size_dt_strings));
- if (version >= 17)
- printf("// size_dt_struct:\t0x%x\n",
- fdt32_to_cpu(bph->size_dt_struct));
- printf("\n");
-
- for (i = 0; ; i++) {
- addr = fdt64_to_cpu(p_rsvmap[i].address);
- size = fdt64_to_cpu(p_rsvmap[i].size);
- if (addr == 0 && size == 0)
- break;
-
- printf("/memreserve/ %llx %llx;\n",
- (unsigned long long)addr, (unsigned long long)size);
- }
-
- p = p_struct;
- while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
-
- /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
-
- if (tag == FDT_BEGIN_NODE) {
- s = p;
- p = PALIGN(p + strlen(s) + 1, 4);
-
- if (*s == '\0')
- s = "/";
-
- printf("%*s%s {\n", depth * shift, "", s);
-
- depth++;
- continue;
- }
-
- if (tag == FDT_END_NODE) {
- depth--;
-
- printf("%*s};\n", depth * shift, "");
- continue;
- }
-
- if (tag == FDT_NOP) {
- printf("%*s// [NOP]\n", depth * shift, "");
- continue;
- }
-
- if (tag != FDT_PROP) {
- fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
- break;
- }
- sz = fdt32_to_cpu(GET_CELL(p));
- s = p_strings + fdt32_to_cpu(GET_CELL(p));
- if (version < 16 && sz >= 8)
- p = PALIGN(p, 8);
- t = p;
-
- p = PALIGN(p + sz, 4);
-
- printf("%*s%s", depth * shift, "", s);
- print_data(t, sz);
- printf(";\n");
- }
-}
-
-
-int main(int argc, char *argv[])
-{
- char *buf;
-
- if (argc < 2) {
- fprintf(stderr, "supply input filename\n");
- return 5;
- }
-
- buf = utilfdt_read(argv[1]);
- if (buf)
- dump_blob(buf);
- else
- return 10;
-
- return 0;
-}
diff --git a/scripts/dtc/fdtoverlay.c b/scripts/dtc/fdtoverlay.c
new file mode 100644
index 000000000000..5350af65679f
--- /dev/null
+++ b/scripts/dtc/fdtoverlay.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
+ *
+ * Author:
+ * Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+#define BUF_INCREMENT 65536
+
+/* Usage related data. */
+static const char usage_synopsis[] =
+ "apply a number of overlays to a base blob\n"
+ " fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
+ "\n"
+ USAGE_TYPE_MSG;
+static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"input", required_argument, NULL, 'i'},
+ {"output", required_argument, NULL, 'o'},
+ {"verbose", no_argument, NULL, 'v'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Input base DT blob",
+ "Output DT blob",
+ "Verbose messages",
+ USAGE_COMMON_OPTS_HELP
+};
+
+int verbose = 0;
+
+static void *apply_one(char *base, const char *overlay, size_t *buf_len,
+ const char *name)
+{
+ char *tmp = NULL;
+ char *tmpo;
+ int ret;
+
+ /*
+ * We take a copies first, because a a failed apply can trash
+ * both the base blob and the overlay
+ */
+ tmpo = xmalloc(fdt_totalsize(overlay));
+
+ do {
+ tmp = xrealloc(tmp, *buf_len);
+ ret = fdt_open_into(base, tmp, *buf_len);
+ if (ret) {
+ fprintf(stderr,
+ "\nFailed to make temporary copy: %s\n",
+ fdt_strerror(ret));
+ goto fail;
+ }
+
+ memcpy(tmpo, overlay, fdt_totalsize(overlay));
+
+ ret = fdt_overlay_apply(tmp, tmpo);
+ if (ret == -FDT_ERR_NOSPACE) {
+ *buf_len += BUF_INCREMENT;
+ }
+ } while (ret == -FDT_ERR_NOSPACE);
+
+ if (ret) {
+ fprintf(stderr, "\nFailed to apply '%s': %s\n",
+ name, fdt_strerror(ret));
+ goto fail;
+ }
+
+ free(base);
+ free(tmpo);
+ return tmp;
+
+fail:
+ free(tmpo);
+ if (tmp)
+ free(tmp);
+
+ return NULL;
+}
+static int do_fdtoverlay(const char *input_filename,
+ const char *output_filename,
+ int argc, char *argv[])
+{
+ char *blob = NULL;
+ char **ovblob = NULL;
+ size_t buf_len;
+ int i, ret = -1;
+
+ blob = utilfdt_read(input_filename, &buf_len);
+ if (!blob) {
+ fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
+ goto out_err;
+ }
+ if (fdt_totalsize(blob) > buf_len) {
+ fprintf(stderr,
+ "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
+ (unsigned long)buf_len, fdt_totalsize(blob));
+ goto out_err;
+ }
+
+ /* allocate blob pointer array */
+ ovblob = xmalloc(sizeof(*ovblob) * argc);
+ memset(ovblob, 0, sizeof(*ovblob) * argc);
+
+ /* read and keep track of the overlay blobs */
+ for (i = 0; i < argc; i++) {
+ size_t ov_len;
+ ovblob[i] = utilfdt_read(argv[i], &ov_len);
+ if (!ovblob[i]) {
+ fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
+ goto out_err;
+ }
+ if (fdt_totalsize(ovblob[i]) > ov_len) {
+ fprintf(stderr,
+"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
+ argv[i], (unsigned long)ov_len,
+ fdt_totalsize(ovblob[i]));
+ goto out_err;
+ }
+ }
+
+ buf_len = fdt_totalsize(blob);
+
+ /* apply the overlays in sequence */
+ for (i = 0; i < argc; i++) {
+ blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
+ if (!blob)
+ goto out_err;
+ }
+
+ fdt_pack(blob);
+ ret = utilfdt_write(output_filename, blob);
+ if (ret)
+ fprintf(stderr, "\nFailed to write '%s'\n",
+ output_filename);
+
+out_err:
+ if (ovblob) {
+ for (i = 0; i < argc; i++) {
+ if (ovblob[i])
+ free(ovblob[i]);
+ }
+ free(ovblob);
+ }
+ free(blob);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int opt, i;
+ char *input_filename = NULL;
+ char *output_filename = NULL;
+
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+
+ case 'i':
+ input_filename = optarg;
+ break;
+ case 'o':
+ output_filename = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ }
+ }
+
+ if (!input_filename)
+ usage("missing input file");
+
+ if (!output_filename)
+ usage("missing output file");
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc <= 0)
+ usage("missing overlay file(s)");
+
+ if (verbose) {
+ printf("input = %s\n", input_filename);
+ printf("output = %s\n", output_filename);
+ for (i = 0; i < argc; i++)
+ printf("overlay[%d] = %s\n", i, argv[i]);
+ }
+
+ if (do_fdtoverlay(input_filename, output_filename, argc, argv))
+ return 1;
+
+ return 0;
+}
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 07f10d2b5d79..4659afbfcbab 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -149,7 +149,7 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
- int off = 0;
+ unsigned int off = 0;
struct marker *m = d.markers;
for_each_marker_of_type(m, LABEL)
@@ -219,7 +219,7 @@ static struct emitter asm_emitter = {
static int stringtable_insert(struct data *d, const char *str)
{
- int i;
+ unsigned int i;
/* FIXME: do this more efficiently? */
@@ -345,7 +345,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
- int i;
+ unsigned int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@@ -446,7 +446,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
- int i;
+ unsigned int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 6cf2fa03b037..3e893073da05 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *fdt)
if (can_assume(VALID_DTB))
return totalsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 91cc6fefe374..17584da25760 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -181,8 +181,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
- *address = fdt64_ld(&re->address);
- *size = fdt64_ld(&re->size);
+ *address = fdt64_ld_(&re->address);
+ *size = fdt64_ld_(&re->size);
return 0;
}
@@ -192,7 +192,7 @@ int fdt_num_mem_rsv(const void *fdt)
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
- if (fdt64_ld(&re->size) == 0)
+ if (fdt64_ld_(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
@@ -370,7 +370,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_ld(&prop->len);
+ *lenp = fdt32_ld_(&prop->len);
return prop;
}
@@ -408,7 +408,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
- if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+ if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@@ -461,7 +461,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -479,7 +479,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
if (!name) {
if (lenp)
@@ -488,13 +488,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
}
*namep = name;
} else {
- *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -519,7 +519,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
- return fdt32_ld(php);
+ return fdt32_ld_(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 68887b969a45..f13458d165d4 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -428,12 +428,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
- } else {
+ } else if (fdt_version(fdt) == 16) {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
+ } else {
+ return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) ||
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 68b543c4dfa2..4c569ee7eb0d 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -377,7 +377,7 @@ int fdt_finish(void *fdt)
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
/* And fix up fields that were keeping intermediate state. */
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
return 0;
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index fe49b5d78938..c42807a7663e 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
#define FDT_FIRST_SUPPORTED_VERSION 0x02
+#define FDT_LAST_COMPATIBLE_VERSION 0x10
#define FDT_LAST_SUPPORTED_VERSION 0x11
/* Error codes: informative error codes */
@@ -101,7 +102,11 @@ extern "C" {
/* FDT_ERR_BADFLAGS: The function was passed a flags field that
* contains invalid flags or an invalid combination of flags. */
-#define FDT_ERR_MAX 18
+#define FDT_ERR_ALIGNMENT 19
+ /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
+ * aligned. */
+
+#define FDT_ERR_MAX 19
/* constants */
#define FDT_MAX_PHANDLE 0xfffffffe
@@ -122,12 +127,10 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/*
- * Alignment helpers:
- * These helpers access words from a device tree blob. They're
- * built to work even with unaligned pointers on platforms (ike
- * ARM) that don't like unaligned loads and stores
+ * External helpers to access words from a device tree blob. They're built
+ * to work even with unaligned pointers on platforms (such as ARMv5) that don't
+ * like unaligned loads and stores.
*/
-
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
const uint8_t *bp = (const uint8_t *)p;
@@ -184,23 +187,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
/**
* fdt_first_subnode() - get offset of first direct subnode
- *
* @fdt: FDT blob
* @offset: Offset of node to check
- * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ *
+ * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
*/
int fdt_first_subnode(const void *fdt, int offset);
/**
* fdt_next_subnode() - get offset of next direct subnode
+ * @fdt: FDT blob
+ * @offset: Offset of previous subnode
*
* After first calling fdt_first_subnode(), call this function repeatedly to
* get direct subnodes of a parent node.
*
- * @fdt: FDT blob
- * @offset: Offset of previous subnode
- * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
- * subnodes
+ * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
*/
int fdt_next_subnode(const void *fdt, int offset);
@@ -225,7 +228,6 @@ int fdt_next_subnode(const void *fdt, int offset);
* Note that this is implemented as a macro and @node is used as
* iterator in the loop. The parent variable be constant or even a
* literal.
- *
*/
#define fdt_for_each_subnode(node, fdt, parent) \
for (node = fdt_first_subnode(fdt, parent); \
@@ -269,17 +271,21 @@ fdt_set_hdr_(size_dt_struct);
/**
* fdt_header_size - return the size of the tree's header
* @fdt: pointer to a flattened device tree
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size(const void *fdt);
/**
- * fdt_header_size_ - internal function which takes a version number
+ * fdt_header_size_ - internal function to get header size from a version number
+ * @version: devicetree version number
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size_(uint32_t version);
/**
* fdt_check_header - sanity check a device tree header
-
* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
@@ -404,8 +410,7 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt)
* highest phandle value in the device tree blob) will be returned in the
* @phandle parameter.
*
- * Returns:
- * 0 on success or a negative error-code on failure
+ * Return: 0 on success or a negative error-code on failure
*/
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
@@ -425,9 +430,11 @@ int fdt_num_mem_rsv(const void *fdt);
/**
* fdt_get_mem_rsv - retrieve one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: pointers to 64-bit variables
+ * @n: index of reserve map entry
+ * @address: pointer to 64-bit variable to hold the start address
+ * @size: pointer to 64-bit variable to hold the size of the entry
*
- * On success, *address and *size will contain the address and size of
+ * On success, @address and @size will contain the address and size of
* the n-th reserve map entry from the device tree blob, in
* native-endian format.
*
@@ -450,6 +457,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* namelen characters of name for matching the subnode name. This is
* useful for finding subnodes based on a portion of a larger string,
* such as a full path.
+ *
+ * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
*/
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
@@ -489,6 +498,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
*
* Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name.
+ *
+ * Return: offset of the node or negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
@@ -588,9 +599,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
/**
* fdt_for_each_property_offset - iterate over all properties of a node
*
- * @property_offset: property offset (int, lvalue)
- * @fdt: FDT blob (const void *)
- * @node: node offset (int)
+ * @property: property offset (int, lvalue)
+ * @fdt: FDT blob (const void *)
+ * @node: node offset (int)
*
* This is actually a wrapper around a for loop and would be used like so:
*
@@ -653,6 +664,9 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
*
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the structure representing the property, or NULL
+ * if not found
*/
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
@@ -745,6 +759,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the property's value or NULL on error
*/
#ifndef SWIG /* Not available in Python */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
@@ -766,10 +782,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* fdt_getprop() retrieves a pointer to the value of the property
- * named 'name' of the node at offset nodeoffset (this will be a
+ * named @name of the node at offset @nodeoffset (this will be a
* pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.
+ * If @lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by @lenp.
*
* returns:
* pointer to the property's value
@@ -814,8 +830,11 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* @name: name of the alias th look up
* @namelen: number of characters of name to consider
*
- * Identical to fdt_get_alias(), but only examine the first namelen
- * characters of name for matching the alias name.
+ * Identical to fdt_get_alias(), but only examine the first @namelen
+ * characters of @name for matching the alias name.
+ *
+ * Return: a pointer to the expansion of the alias named @name, if it exists,
+ * NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt,
@@ -828,7 +847,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
* @name: name of the alias th look up
*
* fdt_get_alias() retrieves the value of a given alias. That is, the
- * value of the property named 'name' in the node /aliases.
+ * value of the property named @name in the node /aliases.
*
* returns:
* a pointer to the expansion of the alias named 'name', if it exists
@@ -1004,14 +1023,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
/**
- * fdt_node_check_compatible: check a node's compatible property
+ * fdt_node_check_compatible - check a node's compatible property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @compatible: string to match against
*
- *
* fdt_node_check_compatible() returns 0 if the given node contains a
- * 'compatible' property with the given string as one of its elements,
+ * @compatible property with the given string as one of its elements,
* it returns non-zero otherwise, or on error.
*
* returns:
@@ -1075,7 +1093,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
* one or more strings, each terminated by \0, as is found in a device tree
* "compatible" property.
*
- * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ * Return: 1 if the string is found in the list, 0 not found, or invalid list
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
@@ -1084,7 +1102,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
- * @return:
+ *
+ * Return:
* the number of strings in the given property
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
@@ -1104,7 +1123,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
- * @return:
+ * return:
* the index of the string in the list of strings
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
@@ -1128,7 +1147,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
- * @return:
+ * Return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
@@ -1217,6 +1236,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* starting from the given index, and using only the first characters
* of the name. It is useful when you want to manipulate only one value of
* an array and you have a string that doesn't end with \0.
+ *
+ * Return: 0 on success, negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
@@ -1330,8 +1351,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
/**
* fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node containing the property
+ * @name: name of the property to change the value of
+ * @val: new value of the 32-bit cell
*
* This is an alternative name for fdt_setprop_inplace_u32()
+ * Return: 0 on success, negative libfdt error number otherwise.
*/
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1403,7 +1429,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
/**
* fdt_create_with_flags - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
*
@@ -1421,7 +1447,7 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
/**
* fdt_create - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
*
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
@@ -1486,7 +1512,8 @@ int fdt_pack(void *fdt);
/**
* fdt_add_mem_rsv - add one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: 64-bit values (native endian)
+ * @address: 64-bit start address of the reserve map entry
+ * @size: 64-bit size of the reserved region
*
* Adds a reserve map entry to the given blob reserving a region at
* address address of length size.
@@ -1691,8 +1718,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
/**
* fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
*
* This is an alternative name for fdt_setprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
uint32_t val)
@@ -1863,8 +1896,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
/**
* fdt_appendprop_cell - append a single cell value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
*
* This is an alternative name for fdt_appendprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1967,13 +2006,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* fdt_add_subnode_namelen - creates a new node based on substring
* @fdt: pointer to the device tree blob
* @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
+ * @name: name of the subnode to create
* @namelen: number of characters of name to consider
*
- * Identical to fdt_add_subnode(), but use only the first namelen
- * characters of name as the name of the new node. This is useful for
+ * Identical to fdt_add_subnode(), but use only the first @namelen
+ * characters of @name as the name of the new node. This is useful for
* creating subnodes based on a portion of a larger string, such as a
* full path.
+ *
+ * Return: structure block offset of the created subnode (>=0),
+ * negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -1992,7 +2034,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
*
* This function will insert data into the blob, and will therefore
* change the offsets of some existing nodes.
-
+ *
* returns:
* structure block offset of the created nodeequested subnode (>=0), on
* success
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index d4e0bd49c037..16bda1906a7b 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -46,6 +46,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
+/*
+ * Internal helpers to access tructural elements of the device tree
+ * blob (rather than for exaple reading integers from within property
+ * values). We assume that we are either given a naturally aligned
+ * address for the platform or if we are not, we are on a platform
+ * where unaligned memory reads will be handled in a graceful manner.
+ * If not the external helpers fdtXX_ld() from libfdt.h can be used
+ * instead.
+ */
+static inline uint32_t fdt32_ld_(const fdt32_t *p)
+{
+ return fdt32_to_cpu(*p);
+}
+
+static inline uint64_t fdt64_ld_(const fdt64_t *p)
+{
+ return fdt64_to_cpu(*p);
+}
+
#define FDT_SW_MAGIC (~FDT_MAGIC)
/**********************************************************************/
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 032df5878ccc..7eacd0248641 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -438,7 +438,7 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
-cell_t propval_cell_n(struct property *prop, int n)
+cell_t propval_cell_n(struct property *prop, unsigned int n)
{
assert(prop->val.len / sizeof(cell_t) >= n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index f5205fb9c1ff..4fdb22a019bd 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -20,7 +20,7 @@ struct search_path {
static struct search_path *search_path_head, **search_path_tail;
/* Detect infinite include recursion. */
-#define MAX_SRCFILE_DEPTH (100)
+#define MAX_SRCFILE_DEPTH (200)
static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
index bc704e2a6a4a..32ff17ffd089 100755
--- a/scripts/dtc/update-dtc-source.sh
+++ b/scripts/dtc/update-dtc-source.sh
@@ -37,6 +37,7 @@ DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c
LIBFDT_SOURCE="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \
fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
+FDTOVERLAY_SOURCE=fdtoverlay.c
get_last_dtc_version() {
git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
@@ -54,7 +55,7 @@ dtc_log=$(git log --oneline ${last_dtc_ver}..)
# Copy the files into the Linux tree
cd $DTC_LINUX_PATH
-for f in $DTC_SOURCE; do
+for f in $DTC_SOURCE $FDTOVERLAY_SOURCE; do
cp ${DTC_UPSTREAM_PATH}/${f} ${f}
git add ${f}
done
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index 054cdd0fdbe8..73a7839603f1 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.6.0-gcbca977e"
+#define DTC_VERSION "DTC 1.6.0-g183df9e9"
diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c
index 4e93c12dc658..e63d32fe142a 100644
--- a/scripts/dtc/yamltree.c
+++ b/scripts/dtc/yamltree.c
@@ -29,11 +29,11 @@ char *yaml_error_name[] = {
(emitter)->problem, __func__, __LINE__); \
})
-static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
+static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, unsigned int len, int width)
{
yaml_event_t event;
void *tag;
- int off, start_offset = markers->offset;
+ unsigned int off, start_offset = markers->offset;
switch(width) {
case 1: tag = "!u8"; break;
@@ -112,7 +112,7 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
{
yaml_event_t event;
- int len = prop->val.len;
+ unsigned int len = prop->val.len;
struct marker *m = prop->val.markers;
/* Emit the property name */
diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh
index 16c0b2ddaa4c..d54dfba15bf2 100755
--- a/scripts/gen_autoksyms.sh
+++ b/scripts/gen_autoksyms.sh
@@ -43,6 +43,9 @@ EOT
sed 's/ko$/mod/' $modlist |
xargs -n1 sed -n -e '2{s/ /\n/g;/^$/!p;}' -- |
cat - "$ksym_wl" |
+# Remove the dot prefix for ppc64; symbol names with a dot (.) hold entry
+# point addresses.
+sed -e 's/^\.//' |
sort -u |
sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$output_file"
diff --git a/scripts/generate_initcall_order.pl b/scripts/generate_initcall_order.pl
new file mode 100755
index 000000000000..1a88d3f1b913
--- /dev/null
+++ b/scripts/generate_initcall_order.pl
@@ -0,0 +1,270 @@
+#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0
+#
+# Generates a linker script that specifies the correct initcall order.
+#
+# Copyright (C) 2019 Google LLC
+
+use strict;
+use warnings;
+use IO::Handle;
+use IO::Select;
+use POSIX ":sys_wait_h";
+
+my $nm = $ENV{'NM'} || die "$0: ERROR: NM not set?";
+my $objtree = $ENV{'objtree'} || '.';
+
+## currently active child processes
+my $jobs = {}; # child process pid -> file handle
+## results from child processes
+my $results = {}; # object index -> [ { level, secname }, ... ]
+
+## reads _NPROCESSORS_ONLN to determine the maximum number of processes to
+## start
+sub get_online_processors {
+ open(my $fh, "getconf _NPROCESSORS_ONLN 2>/dev/null |")
+ or die "$0: ERROR: failed to execute getconf: $!";
+ my $procs = <$fh>;
+ close($fh);
+
+ if (!($procs =~ /^\d+$/)) {
+ return 1;
+ }
+
+ return int($procs);
+}
+
+## writes results to the parent process
+## format: <file index> <initcall level> <base initcall section name>
+sub write_results {
+ my ($index, $initcalls) = @_;
+
+ # sort by the counter value to ensure the order of initcalls within
+ # each object file is correct
+ foreach my $counter (sort { $a <=> $b } keys(%{$initcalls})) {
+ my $level = $initcalls->{$counter}->{'level'};
+
+ # section name for the initcall function
+ my $secname = $initcalls->{$counter}->{'module'} . '__' .
+ $counter . '_' .
+ $initcalls->{$counter}->{'line'} . '_' .
+ $initcalls->{$counter}->{'function'};
+
+ print "$index $level $secname\n";
+ }
+}
+
+## reads a result line from a child process and adds it to the $results array
+sub read_results{
+ my ($fh) = @_;
+
+ # each child prints out a full line w/ autoflush and exits after the
+ # last line, so even if buffered I/O blocks here, it shouldn't block
+ # very long
+ my $data = <$fh>;
+
+ if (!defined($data)) {
+ return 0;
+ }
+
+ chomp($data);
+
+ my ($index, $level, $secname) = $data =~
+ /^(\d+)\ ([^\ ]+)\ (.*)$/;
+
+ if (!defined($index) ||
+ !defined($level) ||
+ !defined($secname)) {
+ die "$0: ERROR: child process returned invalid data: $data\n";
+ }
+
+ $index = int($index);
+
+ if (!exists($results->{$index})) {
+ $results->{$index} = [];
+ }
+
+ push (@{$results->{$index}}, {
+ 'level' => $level,
+ 'secname' => $secname
+ });
+
+ return 1;
+}
+
+## finds initcalls from an object file or all object files in an archive, and
+## writes results back to the parent process
+sub find_initcalls {
+ my ($index, $file) = @_;
+
+ die "$0: ERROR: file $file doesn't exist?" if (! -f $file);
+
+ open(my $fh, "\"$nm\" --defined-only \"$file\" 2>/dev/null |")
+ or die "$0: ERROR: failed to execute \"$nm\": $!";
+
+ my $initcalls = {};
+
+ while (<$fh>) {
+ chomp;
+
+ # check for the start of a new object file (if processing an
+ # archive)
+ my ($path)= $_ =~ /^(.+)\:$/;
+
+ if (defined($path)) {
+ write_results($index, $initcalls);
+ $initcalls = {};
+ next;
+ }
+
+ # look for an initcall
+ my ($module, $counter, $line, $symbol) = $_ =~
+ /[a-z]\s+__initcall__(\S*)__(\d+)_(\d+)_(.*)$/;
+
+ if (!defined($module)) {
+ $module = ''
+ }
+
+ if (!defined($counter) ||
+ !defined($line) ||
+ !defined($symbol)) {
+ next;
+ }
+
+ # parse initcall level
+ my ($function, $level) = $symbol =~
+ /^(.*)((early|rootfs|con|[0-9])s?)$/;
+
+ die "$0: ERROR: invalid initcall name $symbol in $file($path)"
+ if (!defined($function) || !defined($level));
+
+ $initcalls->{$counter} = {
+ 'module' => $module,
+ 'line' => $line,
+ 'function' => $function,
+ 'level' => $level,
+ };
+ }
+
+ close($fh);
+ write_results($index, $initcalls);
+}
+
+## waits for any child process to complete, reads the results, and adds them to
+## the $results array for later processing
+sub wait_for_results {
+ my ($select) = @_;
+
+ my $pid = 0;
+ do {
+ # unblock children that may have a full write buffer
+ foreach my $fh ($select->can_read(0)) {
+ read_results($fh);
+ }
+
+ # check for children that have exited, read the remaining data
+ # from them, and clean up
+ $pid = waitpid(-1, WNOHANG);
+ if ($pid > 0) {
+ if (!exists($jobs->{$pid})) {
+ next;
+ }
+
+ my $fh = $jobs->{$pid};
+ $select->remove($fh);
+
+ while (read_results($fh)) {
+ # until eof
+ }
+
+ close($fh);
+ delete($jobs->{$pid});
+ }
+ } while ($pid > 0);
+}
+
+## forks a child to process each file passed in the command line and collects
+## the results
+sub process_files {
+ my $index = 0;
+ my $njobs = $ENV{'PARALLELISM'} || get_online_processors();
+ my $select = IO::Select->new();
+
+ while (my $file = shift(@ARGV)) {
+ # fork a child process and read it's stdout
+ my $pid = open(my $fh, '-|');
+
+ if (!defined($pid)) {
+ die "$0: ERROR: failed to fork: $!";
+ } elsif ($pid) {
+ # save the child process pid and the file handle
+ $select->add($fh);
+ $jobs->{$pid} = $fh;
+ } else {
+ # in the child process
+ STDOUT->autoflush(1);
+ find_initcalls($index, "$objtree/$file");
+ exit;
+ }
+
+ $index++;
+
+ # limit the number of children to $njobs
+ if (scalar(keys(%{$jobs})) >= $njobs) {
+ wait_for_results($select);
+ }
+ }
+
+ # wait for the remaining children to complete
+ while (scalar(keys(%{$jobs})) > 0) {
+ wait_for_results($select);
+ }
+}
+
+sub generate_initcall_lds() {
+ process_files();
+
+ my $sections = {}; # level -> [ secname, ...]
+
+ # sort results to retain link order and split to sections per
+ # initcall level
+ foreach my $index (sort { $a <=> $b } keys(%{$results})) {
+ foreach my $result (@{$results->{$index}}) {
+ my $level = $result->{'level'};
+
+ if (!exists($sections->{$level})) {
+ $sections->{$level} = [];
+ }
+
+ push(@{$sections->{$level}}, $result->{'secname'});
+ }
+ }
+
+ die "$0: ERROR: no initcalls?" if (!keys(%{$sections}));
+
+ # print out a linker script that defines the order of initcalls for
+ # each level
+ print "SECTIONS {\n";
+
+ foreach my $level (sort(keys(%{$sections}))) {
+ my $section;
+
+ if ($level eq 'con') {
+ $section = '.con_initcall.init';
+ } else {
+ $section = ".initcall${level}.init";
+ }
+
+ print "\t${section} : {\n";
+
+ foreach my $secname (@{$sections->{$level}}) {
+ print "\t\t*(${section}..${secname}) ;\n";
+ }
+
+ print "\t}\n";
+ }
+
+ print "}\n";
+}
+
+generate_initcall_lds();
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 6325bec3f66f..e046e16e4411 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -382,6 +382,9 @@ my $inline_doc_state;
# 'function', 'struct', 'union', 'enum', 'typedef'
my $decl_type;
+# Name of the kernel-doc identifier for non-DOC markups
+my $identifier;
+
my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
my $doc_end = '\*/';
my $doc_com = '\s*\*\s*';
@@ -833,6 +836,7 @@ sub output_blockhead_rst(%) {
next if (defined($nosymbol_table{$section}));
if ($output_selection != OUTPUT_INCLUDE) {
+ print ".. _$section:\n\n";
print "**$section**\n\n";
}
print_lineno($section_start_lines{$section});
@@ -1203,6 +1207,11 @@ sub dump_struct($$) {
$declaration_name = $2;
my $members = $3;
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for $decl_type $identifier. Prototype was for $decl_type $declaration_name instead\n";
+ return;
+ }
+
# ignore members marked private:
$members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
$members =~ s/\/\*\s*private:.*//gosi;
@@ -1391,6 +1400,11 @@ sub dump_enum($$) {
}
if ($members) {
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for enum $identifier. Prototype was for enum $declaration_name instead\n";
+ return;
+ }
+
my %_members;
$members =~ s/\s+$//;
@@ -1451,6 +1465,11 @@ sub dump_typedef($$) {
my $args = $3;
$return_type =~ s/^\s+//;
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n";
+ return;
+ }
+
create_parameterlist($args, ',', $file, $declaration_name);
output_declaration($declaration_name,
@@ -1477,6 +1496,11 @@ sub dump_typedef($$) {
if ($x =~ /typedef.*\s+(\w+)\s*;/) {
$declaration_name = $1;
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for typedef $identifier. Prototype was for typedef $declaration_name instead\n";
+ return;
+ }
+
output_declaration($declaration_name,
'typedef',
{'typedef' => $declaration_name,
@@ -1796,6 +1820,11 @@ sub dump_function($$) {
return;
}
+ if ($identifier ne $declaration_name) {
+ print STDERR "${file}:$.: warning: expecting prototype for $identifier(). Prototype was for $declaration_name() instead\n";
+ return;
+ }
+
my $prms = join " ", @parameterlist;
check_sections($file, $declaration_name, "function", $sectcheck, $prms);
@@ -1878,6 +1907,7 @@ sub tracepoint_munge($) {
"$prototype\n";
} else {
$prototype = "static inline void trace_$tracepointname($tracepointargs)";
+ $identifier = "trace_$identifier";
}
}
@@ -2041,7 +2071,6 @@ sub process_normal() {
#
sub process_name($$) {
my $file = shift;
- my $identifier;
my $descr;
if (/$doc_block/o) {
@@ -2054,12 +2083,19 @@ sub process_name($$) {
} else {
$section = $1;
}
- }
- elsif (/$doc_decl/o) {
+ } elsif (/$doc_decl/o) {
$identifier = $1;
- if (/\s*([\w\s]+?)(\(\))?\s*-/) {
+ if (/\s*([\w\s]+?)(\(\))?\s*([-:].*)?$/) {
$identifier = $1;
}
+ if ($identifier =~ m/^(struct|union|enum|typedef)\b\s*(\S*)/) {
+ $decl_type = $1;
+ $identifier = $2;
+ } else {
+ $decl_type = 'function';
+ $identifier =~ s/^define\s+//;
+ }
+ $identifier =~ s/\s+$//;
$state = STATE_BODY;
# if there's no @param blocks need to set up default section
@@ -2067,7 +2103,7 @@ sub process_name($$) {
$contents = "";
$section = $section_default;
$new_start_line = $. + 1;
- if (/-(.*)/) {
+ if (/[-:](.*)/) {
# strip leading/trailing/multiple spaces
$descr= $1;
$descr =~ s/^\s*//;
@@ -2085,20 +2121,15 @@ sub process_name($$) {
++$warnings;
}
- if ($identifier =~ m/^struct\b/) {
- $decl_type = 'struct';
- } elsif ($identifier =~ m/^union\b/) {
- $decl_type = 'union';
- } elsif ($identifier =~ m/^enum\b/) {
- $decl_type = 'enum';
- } elsif ($identifier =~ m/^typedef\b/) {
- $decl_type = 'typedef';
- } else {
- $decl_type = 'function';
+ if ($identifier eq "") {
+ print STDERR "${file}:$.: warning: wrong kernel-doc identifier on line:\n";
+ print STDERR $_;
+ ++$warnings;
+ $state = STATE_NORMAL;
}
if ($verbose) {
- print STDERR "${file}:$.: info: Scanning doc for $identifier\n";
+ print STDERR "${file}:$.: info: Scanning doc for $decl_type $identifier\n";
}
} else {
print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 6eded325c837..3b261b0f74f0 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -43,11 +43,37 @@ info()
fi
}
+# Generate a linker script to ensure correct ordering of initcalls.
+gen_initcalls()
+{
+ info GEN .tmp_initcalls.lds
+
+ ${PYTHON} ${srctree}/scripts/jobserver-exec \
+ ${PERL} ${srctree}/scripts/generate_initcall_order.pl \
+ ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \
+ > .tmp_initcalls.lds
+}
+
+# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
+# .tmp_symversions.lds
+gen_symversions()
+{
+ info GEN .tmp_symversions.lds
+ rm -f .tmp_symversions.lds
+
+ for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
+ if [ -f ${o}.symversions ]; then
+ cat ${o}.symversions >> .tmp_symversions.lds
+ fi
+ done
+}
+
# Link of vmlinux.o used for section mismatch analysis
# ${1} output file
modpost_link()
{
local objects
+ local lds=""
objects="--whole-archive \
${KBUILD_VMLINUX_OBJS} \
@@ -56,19 +82,57 @@ modpost_link()
${KBUILD_VMLINUX_LIBS} \
--end-group"
- ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
+ gen_initcalls
+ lds="-T .tmp_initcalls.lds"
+
+ if [ -n "${CONFIG_MODVERSIONS}" ]; then
+ gen_symversions
+ lds="${lds} -T .tmp_symversions.lds"
+ fi
+
+ # This might take a while, so indicate that we're doing
+ # an LTO link
+ info LTO ${1}
+ else
+ info LD ${1}
+ fi
+
+ ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
}
objtool_link()
{
+ local objtoolcmd;
local objtoolopt;
+ if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then
+ # Don't perform vmlinux validation unless explicitly requested,
+ # but run objtool on vmlinux.o now that we have an object file.
+ if [ -n "${CONFIG_UNWINDER_ORC}" ]; then
+ objtoolcmd="orc generate"
+ fi
+
+ objtoolopt="${objtoolopt} --duplicate"
+
+ if [ -n "${CONFIG_FTRACE_MCOUNT_USE_OBJTOOL}" ]; then
+ objtoolopt="${objtoolopt} --mcount"
+ fi
+ fi
+
if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then
- objtoolopt="check"
+ objtoolopt="${objtoolopt} --noinstr"
+ fi
+
+ if [ -n "${objtoolopt}" ]; then
+ if [ -z "${objtoolcmd}" ]; then
+ objtoolcmd="check"
+ fi
+ objtoolopt="${objtoolopt} --vmlinux"
if [ -z "${CONFIG_FRAME_POINTER}" ]; then
objtoolopt="${objtoolopt} --no-fp"
fi
- if [ -n "${CONFIG_GCOV_KERNEL}" ]; then
+ if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then
objtoolopt="${objtoolopt} --no-unreachable"
fi
if [ -n "${CONFIG_RETPOLINE}" ]; then
@@ -78,7 +142,7 @@ objtool_link()
objtoolopt="${objtoolopt} --uaccess"
fi
info OBJTOOL ${1}
- tools/objtool/objtool ${objtoolopt} ${1}
+ tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1}
fi
}
@@ -103,13 +167,22 @@ vmlinux_link()
fi
if [ "${SRCARCH}" != "um" ]; then
- objects="--whole-archive \
- ${KBUILD_VMLINUX_OBJS} \
- --no-whole-archive \
- --start-group \
- ${KBUILD_VMLINUX_LIBS} \
- --end-group \
- ${@}"
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
+ # Use vmlinux.o instead of performing the slow LTO
+ # link again.
+ objects="--whole-archive \
+ vmlinux.o \
+ --no-whole-archive \
+ ${@}"
+ else
+ objects="--whole-archive \
+ ${KBUILD_VMLINUX_OBJS} \
+ --no-whole-archive \
+ --start-group \
+ ${KBUILD_VMLINUX_LIBS} \
+ --end-group \
+ ${@}"
+ fi
${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
${strip_debug#-Wl,} \
@@ -225,6 +298,8 @@ cleanup()
{
rm -f .btf.*
rm -f .tmp_System.map
+ rm -f .tmp_initcalls.lds
+ rm -f .tmp_symversions.lds
rm -f .tmp_vmlinux*
rm -f System.map
rm -f vmlinux
@@ -274,7 +349,6 @@ fi;
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
#link vmlinux.o
-info LD vmlinux.o
modpost_link vmlinux.o
objtool_link vmlinux.o
diff --git a/scripts/lto-used-symbollist.txt b/scripts/lto-used-symbollist.txt
new file mode 100644
index 000000000000..38e7bb9ebaae
--- /dev/null
+++ b/scripts/lto-used-symbollist.txt
@@ -0,0 +1,5 @@
+memcpy
+memmove
+memset
+__stack_chk_fail
+__stack_chk_guard
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index 78071681d924..c9e38ad937fd 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD := y
+CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
hostprogs-always-y += modpost mk_elfconfig
always-y += empty.o
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index e377f52dbfa3..9bb6c7edccc4 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -246,5 +246,17 @@ int main(void)
DEVID(auxiliary_device_id);
DEVID_FIELD(auxiliary_device_id, name);
+ DEVID(ssam_device_id);
+ DEVID_FIELD(ssam_device_id, match_flags);
+ DEVID_FIELD(ssam_device_id, domain);
+ DEVID_FIELD(ssam_device_id, category);
+ DEVID_FIELD(ssam_device_id, target);
+ DEVID_FIELD(ssam_device_id, instance);
+ DEVID_FIELD(ssam_device_id, function);
+
+ DEVID(dfl_device_id);
+ DEVID_FIELD(dfl_device_id, type);
+ DEVID_FIELD(dfl_device_id, feature_id);
+
return 0;
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index fb4827027536..7c97fa8e36bc 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1375,6 +1375,40 @@ static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
return 1;
}
+/*
+ * Looks like: ssam:dNcNtNiNfN
+ *
+ * N is exactly 2 digits, where each is an upper-case hex digit.
+ */
+static int do_ssam_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, ssam_device_id, match_flags);
+ DEF_FIELD(symval, ssam_device_id, domain);
+ DEF_FIELD(symval, ssam_device_id, category);
+ DEF_FIELD(symval, ssam_device_id, target);
+ DEF_FIELD(symval, ssam_device_id, instance);
+ DEF_FIELD(symval, ssam_device_id, function);
+
+ sprintf(alias, "ssam:d%02Xc%02X", domain, category);
+ ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
+ ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
+ ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
+
+ return 1;
+}
+
+/* Looks like: dfl:tNfN */
+static int do_dfl_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, dfl_device_id, type);
+ DEF_FIELD(symval, dfl_device_id, feature_id);
+
+ sprintf(alias, "dfl:t%04Xf%04X", type, feature_id);
+
+ add_wildcard(alias);
+ return 1;
+}
+
/* Does namelen bytes of name exactly match the symbol? */
static bool sym_is(const char *name, unsigned namelen, const char *symbol)
{
@@ -1450,6 +1484,8 @@ static const struct devtable devtable[] = {
{"wmi", SIZE_wmi_device_id, do_wmi_entry},
{"mhi", SIZE_mhi_device_id, do_mhi_entry},
{"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
+ {"ssam", SIZE_ssam_device_id, do_ssam_entry},
+ {"dfl", SIZE_dfl_device_id, do_dfl_entry},
};
/* Create MODULE_ALIAS() statements.
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index d6c81657d695..24725e50c7b4 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -17,7 +17,6 @@
#include <ctype.h>
#include <string.h>
#include <limits.h>
-#include <stdbool.h>
#include <errno.h>
#include "modpost.h"
#include "../../include/linux/license.h"
@@ -43,8 +42,9 @@ static int allow_missing_ns_imports;
static bool error_occurred;
enum export {
- export_plain, export_unused, export_gpl,
- export_unused_gpl, export_gpl_future, export_unknown
+ export_plain,
+ export_gpl,
+ export_unknown
};
/* In kernel, this size is defined in linux/module.h;
@@ -84,14 +84,6 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
error_occurred = true;
}
-static inline bool strends(const char *str, const char *postfix)
-{
- if (strlen(str) < strlen(postfix))
- return false;
-
- return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
-}
-
void *do_nofail(void *ptr, const char *expr)
{
if (!ptr)
@@ -301,10 +293,7 @@ static const struct {
enum export export;
} export_list[] = {
{ .str = "EXPORT_SYMBOL", .export = export_plain },
- { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused },
{ .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
- { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl },
- { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
{ .str = "(unknown)", .export = export_unknown },
};
@@ -363,14 +352,8 @@ static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
if (strstarts(secname, "___ksymtab+"))
return export_plain;
- else if (strstarts(secname, "___ksymtab_unused+"))
- return export_unused;
else if (strstarts(secname, "___ksymtab_gpl+"))
return export_gpl;
- else if (strstarts(secname, "___ksymtab_unused_gpl+"))
- return export_unused_gpl;
- else if (strstarts(secname, "___ksymtab_gpl_future+"))
- return export_gpl_future;
else
return export_unknown;
}
@@ -379,14 +362,8 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
{
if (sec == elf->export_sec)
return export_plain;
- else if (sec == elf->export_unused_sec)
- return export_unused;
else if (sec == elf->export_gpl_sec)
return export_gpl;
- else if (sec == elf->export_unused_gpl_sec)
- return export_unused_gpl;
- else if (sec == elf->export_gpl_future_sec)
- return export_gpl_future;
else
return export_unknown;
}
@@ -590,14 +567,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
info->modinfo_len = sechdrs[i].sh_size;
} else if (strcmp(secname, "__ksymtab") == 0)
info->export_sec = i;
- else if (strcmp(secname, "__ksymtab_unused") == 0)
- info->export_unused_sec = i;
else if (strcmp(secname, "__ksymtab_gpl") == 0)
info->export_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_unused_gpl") == 0)
- info->export_unused_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
- info->export_gpl_future_sec = i;
if (sechdrs[i].sh_type == SHT_SYMTAB) {
unsigned int sh_link_idx;
@@ -1988,6 +1959,10 @@ static char *remove_dot(char *s)
size_t m = strspn(s + n + 1, "0123456789");
if (m && (s[n + m] == '.' || s[n + m] == 0))
s[n] = 0;
+
+ /* strip trailing .lto */
+ if (strends(s, ".lto"))
+ s[strlen(s) - 4] = '\0';
}
return s;
}
@@ -2011,6 +1986,9 @@ static void read_symbols(const char *modname)
/* strip trailing .o */
tmp = NOFAIL(strdup(modname));
tmp[strlen(tmp) - 2] = '\0';
+ /* strip trailing .lto */
+ if (strends(tmp, ".lto"))
+ tmp[strlen(tmp) - 4] = '\0';
mod = new_module(tmp);
free(tmp);
}
@@ -2148,36 +2126,13 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
m, s);
break;
- case export_unused_gpl:
- error("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n",
- m, s);
- break;
- case export_gpl_future:
- warn("GPL-incompatible module %s.ko uses future GPL-only symbol '%s'\n",
- m, s);
- break;
case export_plain:
- case export_unused:
case export_unknown:
/* ignore */
break;
}
}
-static void check_for_unused(enum export exp, const char *m, const char *s)
-{
- switch (exp) {
- case export_unused:
- case export_unused_gpl:
- warn("module %s.ko uses symbol '%s' marked UNUSED\n",
- m, s);
- break;
- default:
- /* ignore */
- break;
- }
-}
-
static void check_exports(struct module *mod)
{
struct symbol *s, *exp;
@@ -2208,7 +2163,6 @@ static void check_exports(struct module *mod)
if (!mod->gpl_compatible)
check_for_gpl_usage(exp->export, basename, exp->name);
- check_for_unused(exp->export, basename, exp->name);
}
}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index e6f46eee0af0..c1a895c0d682 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -139,10 +140,7 @@ struct elf_info {
Elf_Sym *symtab_start;
Elf_Sym *symtab_stop;
Elf_Section export_sec;
- Elf_Section export_unused_sec;
Elf_Section export_gpl_sec;
- Elf_Section export_unused_gpl_sec;
- Elf_Section export_gpl_future_sec;
char *strtab;
char *modinfo;
unsigned int modinfo_len;
@@ -180,6 +178,14 @@ static inline unsigned int get_secindex(const struct elf_info *info,
return info->symtab_shndx_start[sym - info->symtab_start];
}
+static inline bool strends(const char *str, const char *postfix)
+{
+ if (strlen(str) < strlen(postfix))
+ return false;
+
+ return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+}
+
/* file2alias.c */
extern unsigned int cross_build;
void handle_moddevtable(struct module *mod, struct elf_info *info,
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index d587f40f1117..760e6baa7eda 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -391,10 +391,14 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
struct md4_ctx md;
char *fname;
char filelist[PATH_MAX + 1];
+ int postfix_len = 1;
+
+ if (strends(modname, ".lto.o"))
+ postfix_len = 5;
/* objects for a module are listed in the first line of *.mod file. */
snprintf(filelist, sizeof(filelist), "%.*smod",
- (int)strlen(modname) - 1, modname);
+ (int)strlen(modname) - postfix_len, modname);
buf = read_text_file(filelist);
diff --git a/scripts/module.lds.S b/scripts/module.lds.S
index 69b9b71a6a47..168cd27e6122 100644
--- a/scripts/module.lds.S
+++ b/scripts/module.lds.S
@@ -11,18 +11,36 @@ SECTIONS {
__ksymtab 0 : { *(SORT(___ksymtab+*)) }
__ksymtab_gpl 0 : { *(SORT(___ksymtab_gpl+*)) }
- __ksymtab_unused 0 : { *(SORT(___ksymtab_unused+*)) }
- __ksymtab_unused_gpl 0 : { *(SORT(___ksymtab_unused_gpl+*)) }
- __ksymtab_gpl_future 0 : { *(SORT(___ksymtab_gpl_future+*)) }
__kcrctab 0 : { *(SORT(___kcrctab+*)) }
__kcrctab_gpl 0 : { *(SORT(___kcrctab_gpl+*)) }
- __kcrctab_unused 0 : { *(SORT(___kcrctab_unused+*)) }
- __kcrctab_unused_gpl 0 : { *(SORT(___kcrctab_unused_gpl+*)) }
- __kcrctab_gpl_future 0 : { *(SORT(___kcrctab_gpl_future+*)) }
.init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) }
__jump_table 0 : ALIGN(8) { KEEP(*(__jump_table)) }
+
+ __patchable_function_entries : { *(__patchable_function_entries) }
+
+ /*
+ * With CONFIG_LTO_CLANG, LLD always enables -fdata-sections and
+ * -ffunction-sections, which increases the size of the final module.
+ * Merge the split sections in the final binary.
+ */
+ .bss : {
+ *(.bss .bss.[0-9a-zA-Z_]*)
+ *(.bss..L*)
+ }
+
+ .data : {
+ *(.data .data.[0-9a-zA-Z_]*)
+ *(.data..L*)
+ }
+
+ .rodata : {
+ *(.rodata .rodata.[0-9a-zA-Z_]*)
+ *(.rodata..L*)
+ }
+
+ .text : { *(.text .text.[0-9a-zA-Z_]*) }
}
/* bring in arch-specific sections */
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 56c801502b9a..867860ea57da 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -265,7 +265,11 @@ if ($arch eq "x86_64") {
# force flags for this arch
$ld .= " -m shlelf_linux";
- $objcopy .= " -O elf32-sh-linux";
+ if ($endian eq "big") {
+ $objcopy .= " -O elf32-shbig-linux";
+ } else {
+ $objcopy .= " -O elf32-sh-linux";
+ }
} elsif ($arch eq "powerpc") {
my $ldemulation;
diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py
index bc87200f9c7c..cbdb5c83c08f 100755
--- a/scripts/spdxcheck.py
+++ b/scripts/spdxcheck.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# Copyright Thomas Gleixner <tglx@linutronix.de>
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
index 953f4a2de1e5..2e3ba91a5072 100644
--- a/scripts/spelling.txt
+++ b/scripts/spelling.txt
@@ -103,6 +103,7 @@ alloated||allocated
allocatote||allocate
allocatrd||allocated
allocte||allocate
+allocted||allocated
allpication||application
alocate||allocate
alogirhtms||algorithms
@@ -339,6 +340,7 @@ comppatible||compatible
compres||compress
compresion||compression
comression||compression
+comunicate||communicate
comunication||communication
conbination||combination
conditionaly||conditionally
@@ -466,6 +468,7 @@ developpment||development
deveolpment||development
devided||divided
deviece||device
+devision||division
diable||disable
dicline||decline
dictionnary||dictionary
@@ -479,6 +482,7 @@ difinition||definition
digial||digital
dimention||dimension
dimesions||dimensions
+diconnected||disconnected
disgest||digest
dispalying||displaying
diplay||display
@@ -518,6 +522,7 @@ downlads||downloads
droped||dropped
droput||dropout
druing||during
+dyanmic||dynamic
dynmaic||dynamic
eanable||enable
eanble||enable
@@ -542,6 +547,7 @@ encrupted||encrypted
encrypiton||encryption
encryptio||encryption
endianess||endianness
+enpoint||endpoint
enhaced||enhanced
enlightnment||enlightenment
enqueing||enqueuing
@@ -566,6 +572,7 @@ estbalishment||establishment
etsablishment||establishment
etsbalishment||establishment
evalution||evaluation
+exeeds||exceeds
excecutable||executable
exceded||exceeded
exceds||exceeds
@@ -574,6 +581,7 @@ excellant||excellent
execeeded||exceeded
execeeds||exceeds
exeed||exceed
+exeeds||exceeds
exeuction||execution
existance||existence
existant||existent
@@ -641,6 +649,7 @@ forwardig||forwarding
frambuffer||framebuffer
framming||framing
framwork||framework
+frequence||frequency
frequncy||frequency
frequancy||frequency
frome||from
@@ -683,10 +692,12 @@ handfull||handful
hanlde||handle
hanled||handled
happend||happened
+hardare||hardware
harware||hardware
havind||having
heirarchically||hierarchically
helpfull||helpful
+heterogenous||heterogeneous
hexdecimal||hexadecimal
hybernate||hibernate
hierachy||hierarchy
@@ -731,6 +742,7 @@ inconsistant||inconsistent
increas||increase
incremeted||incremented
incrment||increment
+incuding||including
inculde||include
indendation||indentation
indended||intended
@@ -741,6 +753,7 @@ indiate||indicate
indicat||indicate
inexpect||inexpected
inferface||interface
+infinit||infinite
infomation||information
informatiom||information
informations||information
@@ -771,6 +784,7 @@ instace||instance
instal||install
instanciate||instantiate
instanciated||instantiated
+instuments||instruments
insufficent||insufficient
inteface||interface
integreated||integrated
@@ -869,12 +883,14 @@ mailformed||malformed
malplaced||misplaced
malplace||misplace
managable||manageable
+managament||management
managment||management
mangement||management
manger||manager
manoeuvering||maneuvering
manufaucturing||manufacturing
mappping||mapping
+maping||mapping
matchs||matches
mathimatical||mathematical
mathimatic||mathematic
@@ -886,6 +902,7 @@ meetign||meeting
memeory||memory
memmber||member
memoery||memory
+memroy||memory
ment||meant
mergable||mergeable
mesage||message
@@ -999,6 +1016,7 @@ overlaping||overlapping
overide||override
overrided||overridden
overriden||overridden
+overrrun||overrun
overun||overrun
overwritting||overwriting
overwriten||overwritten
@@ -1035,6 +1053,7 @@ peforming||performing
peice||piece
pendantic||pedantic
peprocessor||preprocessor
+perfomance||performance
perfoming||performing
perfomring||performing
periperal||peripheral
@@ -1100,6 +1119,7 @@ prodecure||procedure
progamming||programming
progams||programs
progess||progress
+programable||programmable
programers||programmers
programm||program
programms||programs
@@ -1144,6 +1164,7 @@ recieved||received
recieve||receive
reciever||receiver
recieves||receives
+recieving||receiving
recogniced||recognised
recognizeable||recognizable
recommanded||recommended
@@ -1247,6 +1268,7 @@ searchs||searches
secquence||sequence
secund||second
segement||segment
+seleted||selected
semaphone||semaphore
senario||scenario
senarios||scenarios
@@ -1263,6 +1285,7 @@ seqeunce||sequence
seqeuncer||sequencer
seqeuencer||sequencer
sequece||sequence
+sequemce||sequence
sequencial||sequential
serivce||service
serveral||several
@@ -1333,6 +1356,7 @@ suble||subtle
substract||subtract
submited||submitted
submition||submission
+succeded||succeeded
suceed||succeed
succesfully||successfully
succesful||successful
@@ -1353,6 +1377,7 @@ supportin||supporting
suppoted||supported
suppported||supported
suppport||support
+supprot||support
supress||suppress
surpressed||suppressed
surpresses||suppresses
@@ -1401,6 +1426,7 @@ thresold||threshold
throught||through
trackling||tracking
troughput||throughput
+trys||tries
thses||these
tiggers||triggers
tiggered||triggered
@@ -1414,7 +1440,9 @@ traking||tracking
tramsmitted||transmitted
tramsmit||transmit
tranasction||transaction
+tranceiver||transceiver
tranfer||transfer
+tranmission||transmission
transcevier||transceiver
transciever||transceiver
transferd||transferred
@@ -1468,6 +1496,7 @@ unnecesary||unnecessary
unneedingly||unnecessarily
unnsupported||unsupported
unmached||unmatched
+unprecise||imprecise
unregester||unregister
unresgister||unregister
unrgesiter||unregister
@@ -1503,6 +1532,7 @@ varient||variant
vaule||value
verbse||verbose
veify||verify
+veriosn||version
verisons||versions
verison||version
verson||version
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install
index 828a8615a918..b5f9fd5b2880 100755
--- a/scripts/sphinx-pre-install
+++ b/scripts/sphinx-pre-install
@@ -728,8 +728,8 @@ sub check_needs()
$need_virtualenv = 1;
}
if ($1 < 3) {
- # Complain if it finds python2 (or worse)
- printf "Warning: python$1 support is deprecated. Use it with caution!\n";
+ # Fail if it finds python2 (or worse)
+ die "Python 3 is required to build the kernel docs\n";
}
} else {
die "Warning: couldn't identify $python_cmd version!";
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 0968a3070eff..a92acc703f9b 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -15,7 +15,7 @@ BEGIN {
vernum = "[0-9]+([.]?[0-9]+)+"
libc = "libc[.]so[.][0-9]+$"
- libcpp = "(libg|stdc)[+]+[.]so[.][0-9]+$"
+ libcpp = "(libg|stdc)[+]+[.]so([.][0-9]+)+$"
printversion("GNU C", version("gcc -dumpversion"))
printversion("GNU Make", version("make --version"))
@@ -37,12 +37,10 @@ BEGIN {
printversion("Bison", version("bison --version"))
printversion("Flex", version("flex --version"))
- while ("ldconfig -p 2>/dev/null" | getline > 0) {
- if ($NF ~ libc && !seen[ver = version("readlink " $NF)]++)
- printversion("Linux C Library", ver)
- else if ($NF ~ libcpp && !seen[ver = version("readlink " $NF)]++)
- printversion("Linux C++ Library", ver)
- }
+ while ("ldconfig -p 2>/dev/null" | getline > 0)
+ if ($NF ~ libc || $NF ~ libcpp)
+ if (!seen[ver = version("readlink " $NF)]++)
+ printversion("Linux C" ($NF ~ libcpp? "++" : "") " Library", ver)
printversion("Dynamic linker (ldd)", version("ldd --version"))
printversion("Procps", version("ps --version"))