summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backport/Kconfig.integrate36
-rw-r--r--backport/Makefile.kernel13
-rw-r--r--backport/backport-include/backport/backport.h5
-rw-r--r--backport/compat/Makefile4
-rw-r--r--backport/compat/main.c8
-rw-r--r--devel/doc/kconfig-operation5
-rwxr-xr-xgentree.py72
-rw-r--r--integration-patches/0001-enable-backports/0001-enable-backports-built-in.patch40
-rw-r--r--lib/bpversion.py48
-rw-r--r--lib/kconfig.py67
10 files changed, 291 insertions, 7 deletions
diff --git a/backport/Kconfig.integrate b/backport/Kconfig.integrate
new file mode 100644
index 00000000..f64a3f6e
--- /dev/null
+++ b/backport/Kconfig.integrate
@@ -0,0 +1,36 @@
+config BACKPORT_INTEGRATE
+ bool
+ def_bool y
+
+config BACKPORT_DIR
+ string
+ default "%%BACKPORT_DIR%%"
+
+config BACKPORT_VERSION
+ string
+ default "%%BACKPORTS_VERSION%%"
+
+config BACKPORT_KERNEL_VERSION
+ string
+ default "%%BACKPORTED_KERNEL_VERSION%%"
+
+config BACKPORT_KERNEL_NAME
+ string
+ default "%%BACKPORTED_KERNEL_NAME%%"
+
+menuconfig BACKPORT_LINUX
+ bool "Backport %%BACKPORTED_KERNEL_NAME%% %%BACKPORTED_KERNEL_VERSION%% (backports %%BACKPORTS_VERSION%%)"
+ default n
+ ---help---
+ Enabling this will let give you the opportunity to use features and
+ drivers backported from %%BACKPORTED_KERNEL_NAME%% %%BACKPORTED_KERNEL_VERSION%%
+ on the kernel your are using. This is experimental and you should
+ say no unless you'd like to help test things or want to help debug
+ this should we run into any issues.
+
+if BACKPORT_LINUX
+
+source "$BACKPORT_DIR/Kconfig.versions"
+source "$BACKPORT_DIR/Kconfig.sources"
+
+endif # BACKPORT_LINUX
diff --git a/backport/Makefile.kernel b/backport/Makefile.kernel
index a63184bb..c57b2d3c 100644
--- a/backport/Makefile.kernel
+++ b/backport/Makefile.kernel
@@ -1,3 +1,4 @@
+ifeq ($(CONFIG_BACKPORT_INTEGRATE),)
# Since 2.6.21, try-run is available, but cc-disable-warning
# was only added later, so we add it here ourselves:
backport-cc-disable-warning = $(call try-run,\
@@ -17,6 +18,18 @@ NOSTDINC_FLAGS := \
$(CFLAGS)
export backport_srctree = $(M)
+else
+export BACKPORT_DIR = backports/
+export backport_srctree = $(BACKPORT_DIR)
+NOSTDINC_FLAGS := \
+ -I$(BACKPORT_DIR)/backport-include/ \
+ -I$(BACKPORT_DIR)/backport-include/uapi \
+ -I$(BACKPORT_DIR)/include/ \
+ -I$(BACKPORT_DIR)/include/uapi \
+ -include $(BACKPORT_DIR)/backport-include/backport/backport.h \
+ $(CFLAGS)
+endif
+
obj-y += compat/
diff --git a/backport/backport-include/backport/backport.h b/backport/backport-include/backport/backport.h
index 7cf21aa0..d1d3b102 100644
--- a/backport/backport-include/backport/backport.h
+++ b/backport/backport-include/backport/backport.h
@@ -1,11 +1,16 @@
#ifndef __BACKPORT_H
#define __BACKPORT_H
+#include <generated/autoconf.h>
+#ifndef CONFIG_BACKPORT_INTEGRATE
#include <backport/autoconf.h>
+#endif
#include <linux/kconfig.h>
#ifndef __ASSEMBLY__
#define LINUX_BACKPORT(__sym) backport_ ##__sym
+#ifndef CONFIG_BACKPORT_INTEGRATE
#include <backport/checks.h>
#endif
+#endif
#endif /* __BACKPORT_H */
diff --git a/backport/compat/Makefile b/backport/compat/Makefile
index e787763b..f14b5160 100644
--- a/backport/compat/Makefile
+++ b/backport/compat/Makefile
@@ -1,5 +1,9 @@
ccflags-y += -I$(src)
+ifeq ($(CONFIG_BACKPORT_INTEGRATE),)
obj-m += compat.o
+else
+obj-y += compat.o
+endif
compat-y += main.o
# Kernel backport compatibility code
diff --git a/backport/compat/main.c b/backport/compat/main.c
index 04ebbfd5..5d45e3da 100644
--- a/backport/compat/main.c
+++ b/backport/compat/main.c
@@ -71,8 +71,14 @@ static int __init backport_init(void)
#ifdef BACKPORTS_GIT_TRACKED
printk(KERN_INFO BACKPORTS_GIT_TRACKED "\n");
#else
+
+#ifdef CONFIG_BACKPORT_INTEGRATE
+ printk(KERN_INFO "Backport integrated by backports.git " CPTCFG_VERSION "\n");
+#else
printk(KERN_INFO "Backport generated by backports.git " CPTCFG_VERSION "\n");
-#endif
+#endif /* CONFIG_BACKPORT_INTEGRATE */
+
+#endif /* BACKPORTS_GIT_TRACKED */
return 0;
}
diff --git a/devel/doc/kconfig-operation b/devel/doc/kconfig-operation
index ddb4de77..35e198c6 100644
--- a/devel/doc/kconfig-operation
+++ b/devel/doc/kconfig-operation
@@ -73,6 +73,11 @@ This allows code to, for example, have "#ifdef CONFIG_PM" which can only
be set or cleared in the kernel, not in the backport configuration. Since
this is needed, a transformation step is done at backport creation time.
+When using Linux backports to integrate into an existing Linux tree
+the CONFIG_BACKPORT_ prefix is used, this allows a CONFIG_BACKPORT_
+symbol to depend on the non-backported respective symbol to be selected
+allowing these to be mutually exclusive.
+
Backport creation for Kconfig
-------------------------------
diff --git a/gentree.py b/gentree.py
index 90334ef7..00e2d46f 100755
--- a/gentree.py
+++ b/gentree.py
@@ -16,6 +16,7 @@ from lib import bpgpg as gpg
from lib import bpkup as kup
from lib.tempdir import tempdir
from lib import bpreqs as reqs
+from lib import bpversion as gen_version
class Bp_Identity(object):
"""
@@ -233,6 +234,9 @@ def add_automatic_backports(args):
export = re.compile(r'^EXPORT_SYMBOL(_GPL)?\((?P<sym>[^\)]*)\)')
bpi = kconfig.get_backport_info(os.path.join(args.bpid.target_dir, 'compat', 'Kconfig'))
configtree = kconfig.ConfigTree(os.path.join(args.bpid.target_dir, 'Kconfig'), args.bpid)
+ ignore=['Kconfig.kernel', 'Kconfig.versions']
+ configtree.verify_sources(ignore=ignore)
+ git_debug_snapshot(args, "verify sources for automatic backports")
all_selects = configtree.all_selects()
for sym, vals in bpi.items():
if sym.startswith('BPAUTO_BUILD_'):
@@ -640,6 +644,9 @@ def _main():
'and we use git ls-tree to get the files.')
parser.add_argument('--clean', const=True, default=False, action="store_const",
help='Clean output directory instead of erroring if it isn\'t empty')
+ parser.add_argument('--integrate', const=True, default=False, action="store_const",
+ help='Integrate a future backported kernel solution into ' +
+ 'an older kernel tree source directory.')
parser.add_argument('--refresh', const=True, default=False, action="store_const",
help='Refresh patches as they are applied, the source dir will be modified!')
parser.add_argument('--base-name', metavar='<name>', type=str, default='Linux',
@@ -679,9 +686,8 @@ def _main():
# same prefix for packaging as with kernel integration but
# there are already some users of the CPTCFG prefix.
bpid = None
- integrate = False
- if integrate:
- bpid = Bp_Identity(integrate = integrate,
+ if args.integrate:
+ bpid = Bp_Identity(integrate = args.integrate,
kconfig_prefix = 'CONFIG_',
project_prefix = 'BACKPORT_',
project_dir = args.outdir,
@@ -690,7 +696,7 @@ def _main():
kconfig_source_var = '$BACKPORT_DIR',
)
else:
- bpid = Bp_Identity(integrate = integrate,
+ bpid = Bp_Identity(integrate = args.integrate,
kconfig_prefix = 'CPTCFG_',
project_prefix = '',
project_dir = args.outdir,
@@ -764,6 +770,11 @@ def process(kerneldir, copy_list_file, git_revision=None,
test_cocci, profile_cocci)
rel_prep = None
+ if bpid.integrate:
+ if args.kup_test or args.test_cocci or args.profile_cocci or args.refresh:
+ logwrite('Cannot use integration with:\n\tkup_test\n\ttest_cocci\n\tprofile_cocci\n\trefresh\n');
+ sys.exit(1)
+
# start processing ...
if (args.kup or args.kup_test):
git_paranoia(source_dir, logwrite)
@@ -798,6 +809,10 @@ def process(kerneldir, copy_list_file, git_revision=None,
check_output_dir(bpid.target_dir, args.clean)
# do the copy
+ backport_integrate_files = [
+ ('Makefile.kernel', 'Makefile'),
+ ('Kconfig.integrate', 'Kconfig'),
+ ]
backport_package_files = [(x, x) for x in [
'Makefile',
'kconf/',
@@ -819,6 +834,8 @@ def process(kerneldir, copy_list_file, git_revision=None,
if not bpid.integrate:
backport_files += backport_package_files
+ else:
+ backport_files += backport_integrate_files
if not args.git_revision:
logwrite('Copy original source files ...')
@@ -888,6 +905,21 @@ def process(kerneldir, copy_list_file, git_revision=None,
apply_patches(args, "backport", source_dir, 'patches', bpid.target_dir, logwrite)
+ # Kernel integration requires Kconfig.versions already generated for you,
+ # we cannot do this for a package as we have no idea what kernel folks
+ # will be using.
+ if bpid.integrate:
+ kver = gen_version.kernelversion(bpid.project_dir)
+ rel_specs = gen_version.get_rel_spec_stable(kver)
+ if not rel_specs:
+ logwrite('Cannot parse source kernel version, update parser')
+ sys.exit(1)
+ data = gen_version.genkconfig_versions(rel_specs)
+ fo = open(os.path.join(bpid.target_dir, 'Kconfig.versions'), 'w')
+ fo.write(data)
+ fo.close()
+ git_debug_snapshot(args, "generate kernel version requirement Kconfig file")
+
# some post-processing is required
configtree = kconfig.ConfigTree(os.path.join(bpid.target_dir, 'Kconfig'), bpid)
ignore=['Kconfig.kernel', 'Kconfig.versions']
@@ -905,6 +937,15 @@ def process(kerneldir, copy_list_file, git_revision=None,
configtree.force_tristate_modular()
git_debug_snapshot(args, "force tristate options modular")
+ ignore = [os.path.join(bpid.target_dir, x) for x in [
+ 'Kconfig.package.hacks',
+ 'Kconfig.versions',
+ 'Kconfig',
+ ]
+ ]
+ configtree.adjust_backported_configs(ignore=ignore, orig_symbols=orig_symbols)
+ git_debug_snapshot(args, "adjust backports config symbols we port")
+
configtree.modify_selects()
git_debug_snapshot(args, "convert select to depends on")
@@ -944,8 +985,15 @@ def process(kerneldir, copy_list_file, git_revision=None,
# rewrite Makefile and source symbols
+ # symbols we know only we can provide under the backport project prefix
+ # for which we need an exception.
+ skip_orig_syms = [ bpid.project_prefix + x for x in [
+ 'INTEGRATE',
+ ]
+ ]
+ parse_orig_syms = [x for x in orig_symbols if x not in skip_orig_syms ]
regexes = []
- for some_symbols in [orig_symbols[i:i + 50] for i in range(0, len(orig_symbols), 50)]:
+ for some_symbols in [parse_orig_syms[i:i + 50] for i in range(0, len(parse_orig_syms), 50)]:
r = 'CONFIG_((' + '|'.join([s + '(_MODULE)?' for s in some_symbols]) + ')([^A-Za-z0-9_]|$))'
regexes.append(re.compile(r, re.MULTILINE))
for root, dirs, files in os.walk(bpid.target_dir):
@@ -967,7 +1015,10 @@ def process(kerneldir, copy_list_file, git_revision=None,
git_debug_snapshot(args, "rename config symbol / srctree usage")
# disable unbuildable Kconfig symbols and stuff Makefiles that doesn't exist
- maketree = make.MakeTree(os.path.join(bpid.target_dir, 'Makefile.kernel'))
+ if bpid.integrate:
+ maketree = make.MakeTree(os.path.join(bpid.target_dir, 'Makefile'))
+ else:
+ maketree = make.MakeTree(os.path.join(bpid.target_dir, 'Makefile.kernel'))
disable_kconfig = []
disable_makefile = []
for sym in maketree.get_impossible_symbols():
@@ -1017,6 +1068,15 @@ def process(kerneldir, copy_list_file, git_revision=None,
fo.close()
git_debug_snapshot(args, "disable unsatisfied Makefile parts")
+ if bpid.integrate:
+ f = open(os.path.join(bpid.project_dir, 'Kconfig'), 'a')
+ f.write('source "backports/Kconfig"\n')
+ f.close()
+ git_debug_snapshot(args, "hooked backport to top level Kconfig")
+
+ apply_patches(args, "integration", source_dir, 'integration-patches/',
+ bpid.project_dir, logwrite)
+
if (args.kup or args.kup_test):
req = reqs.Req()
req.kup()
diff --git a/integration-patches/0001-enable-backports/0001-enable-backports-built-in.patch b/integration-patches/0001-enable-backports/0001-enable-backports-built-in.patch
new file mode 100644
index 00000000..d66b203d
--- /dev/null
+++ b/integration-patches/0001-enable-backports/0001-enable-backports-built-in.patch
@@ -0,0 +1,40 @@
+Allow backports to be integrated into vmlinux.
+
+diff --git a/Makefile b/Makefile
+index 6d1e304..de26b18 100644
+--- a/Makefile
++++ b/Makefile
+@@ -542,6 +542,7 @@ scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
+ $(Q)$(MAKE) $(build)=$(@)
+
+ # Objects we will link into vmlinux / subdirs we need to visit
++backports-y := backports/
+ init-y := init/
+ drivers-y := drivers/ sound/ firmware/
+ net-y := net/
+@@ -820,13 +821,16 @@ core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+
+ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
+ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
++ $(backports-y) $(backports-m) \
+ $(net-y) $(net-m) $(libs-y) $(libs-m)))
+
+ vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
+ $(init-n) $(init-) \
+ $(core-n) $(core-) $(drivers-n) $(drivers-) \
++ $(backports-n) $(backports-) \
+ $(net-n) $(net-) $(libs-n) $(libs-))))
+
++backports-y := $(patsubst %/, %/built-in.o, $(backports-y))
+ init-y := $(patsubst %/, %/built-in.o, $(init-y))
+ core-y := $(patsubst %/, %/built-in.o, $(core-y))
+ drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
+@@ -837,7 +841,7 @@ libs-y := $(libs-y1) $(libs-y2)
+
+ # Externally visible symbols (used by link-vmlinux.sh)
+ export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
+-export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)
++export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y) $(backports-y)
+ export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
+ export LDFLAGS_vmlinux
+ # used by scripts/pacmage/Makefile
diff --git a/lib/bpversion.py b/lib/bpversion.py
new file mode 100644
index 00000000..aefdcf0c
--- /dev/null
+++ b/lib/bpversion.py
@@ -0,0 +1,48 @@
+import subprocess, os, re
+
+class VersionError(Exception):
+ pass
+class ExecutionError(VersionError):
+ def __init__(self, errcode):
+ self.error_code = errcode
+
+def _check(process):
+ if process.returncode != 0:
+ raise ExecutionError(process.returncode)
+
+def get_rel_spec_stable(rel):
+ """
+ Returns release specs for a linux-stable backports based release.
+ """
+ m = None
+ if ("rc" in rel):
+ m = re.match(r"v*(?P<VERSION>\d+)\.+" \
+ "(?P<PATCHLEVEL>\d+)[.]*" \
+ "(?P<SUBLEVEL>\d*)" \
+ "[-rc]+(?P<RC_VERSION>\d+)",
+ rel)
+ else:
+ m = re.match(r"(?P<VERSION>\d+)\.+" \
+ "(?P<PATCHLEVEL>\d+)[.]*" \
+ "(?P<SUBLEVEL>\d*)",
+ rel)
+ if (not m):
+ return m
+ return m.groupdict()
+
+def kernelversion(tree):
+ cmd = ['make', '--no-print-directory', '-C', tree, 'kernelversion' ]
+ process = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ close_fds=True, universal_newlines=True)
+ stdout = process.communicate()[0]
+ process.wait()
+ _check(process)
+ return stdout.strip()
+
+def genkconfig_versions(rel_specs):
+ data = ''
+ for i in range(int(rel_specs['PATCHLEVEL']) + 1, 99):
+ data += "config BACKPORT_KERNEL_%s_%s\n" % (rel_specs['VERSION'], i)
+ data += " def_bool y\n"
+ return data
diff --git a/lib/kconfig.py b/lib/kconfig.py
index ca3af63a..ea9c121c 100644
--- a/lib/kconfig.py
+++ b/lib/kconfig.py
@@ -137,6 +137,73 @@ class ConfigTree(object):
outf.write(out)
outf.close()
+ def _mod_kconfig_line(self, l, orig_symbols):
+ if self.bpid.project_prefix != '':
+ for sym in orig_symbols:
+ if sym in l:
+ return re.sub(r' (' + sym + ')', r' ' + self.bpid.project_prefix + '\\1', l)
+ return l
+
+ def adjust_backported_configs(self, ignore=[], orig_symbols=[]):
+ m = None
+ old_l = None
+ for nf in self._walk(self.rootfile):
+ if os.path.join(self.bpid.target_dir, nf) in ignore:
+ continue
+ out = ''
+ for l in open(os.path.join(self.bpid.target_dir, nf), 'r'):
+ n = cfg_line.match(l)
+ if n:
+ m = n
+ old_l = l
+ continue
+ # We're now on the second line for the config symbol
+ if m:
+ built_in_sym = m.group('sym')
+ if self.bpid.project_prefix != '':
+ built_in_sym = re.sub(r'' + self.bpid.project_prefix + '(.*)', r'\1', m.group('sym'))
+ # These are things that we carry as part of our backports
+ # module or things we automatically copy over into our
+ # backports module. What we want to do is ensure that we
+ # always negate a backported symbol we provide with the one
+ # provided by the old kernel.
+ #
+ # Note that this means that since project_prefix is empty
+ # it likely means the kconfig getenv() trick was used to
+ # backport and when that's used the same symbol is used,
+ # that means you can't easily negate an internal symbol
+ # as kconfig will always apply the kconfig_prefix.
+ #
+ # XXX: only do this for symbols that have C files
+ # depending on it
+ if self.bpid.project_prefix != '' and self.bpid.project_prefix in m.group('sym'):
+ out += old_l
+ out += l
+ out += "\tdepends on !%s\n" % (built_in_sym)
+ else:
+ # First rewrite the upstream symbol with our prefix if
+ # needed
+ if self.bpid.project_prefix != '':
+ out += m.group('opt') + ' ' + self.bpid.project_prefix + m.group('sym') + '\n'
+ out += l
+ # Packaging uses the checks.h but that's a reactive
+ # measure, this is proactive.
+ if not self.bpid.integrate:
+ # This doesn't happen right now as packaging
+ # always uses an empty project prefix.
+ out += "\tdepends on %s!=y\n" % (built_in_sym)
+ else:
+ out += "\tdepends on !%s\n" % (built_in_sym)
+ else:
+ out += m.group('opt') + ' ' + m.group('sym') + '\n'
+ out += l
+ m = None
+ else:
+ out += self._mod_kconfig_line(l, orig_symbols)
+ outf = open(os.path.join(self.bpid.target_dir, nf), 'w')
+ outf.write(out)
+ outf.close()
+
def symbols(self):
syms = []
for nf in self._walk(self.rootfile):