From 65e62037dd13840f9638632f5a6048c677a68a74 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Feb 2023 13:19:12 -0700 Subject: moveconfig: Add an option to compare Kconfig against source Sometimes the Makefile rules or source code refers to Kconfig options which don't exist. Update the moveconfig tool to check this and produce a series of reports about inconsistencies. This can then be used to generate patches to correct the problems. Signed-off-by: Simon Glass --- tools/moveconfig.py | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) (limited to 'tools') diff --git a/tools/moveconfig.py b/tools/moveconfig.py index 8f084a6070a..c4d72ede368 100755 --- a/tools/moveconfig.py +++ b/tools/moveconfig.py @@ -93,6 +93,18 @@ SIZES = { RE_REMOVE_DEFCONFIG = re.compile(r'(.*)_defconfig') +# CONFIG symbols present in the build system (from Linux) but not actually used +# in U-Boot; KCONFIG symbols +IGNORE_SYMS = ['DEBUG_SECTION_MISMATCH', 'FTRACE_MCOUNT_RECORD', 'GCOV_KERNEL', + 'GCOV_PROFILE_ALL', 'KALLSYMS', 'KASAN', 'MODVERSIONS', 'SHELL', + 'TPL_BUILD', 'VPL_BUILD', 'IS_ENABLED', 'FOO', 'IF_ENABLED_INT', + 'IS_ENABLED_', 'IS_ENABLED_1', 'IS_ENABLED_2', 'IS_ENABLED_3', + 'SPL_', 'TPL_', 'SPL_FOO', 'TPL_FOO', 'TOOLS_FOO', + 'ACME', 'SPL_ACME', 'TPL_ACME', 'TRACE_BRANCH_PROFILING', + 'VAL', '_UNDEFINED', 'SPL_BUILD', ] + +SPL_PREFIXES = ['SPL_', 'TPL_', 'VPL_', 'TOOLS_'] + ### helper functions ### def check_top_directory(): """Exit if we are not at the top of source directory.""" @@ -536,6 +548,7 @@ class KconfigScanner: os.environ['srctree'] = os.getcwd() os.environ['UBOOTVERSION'] = 'dummy' os.environ['KCONFIG_OBJDIR'] = '' + os.environ['CC'] = 'gcc' self.conf = kconfiglib.Kconfig() @@ -1593,6 +1606,319 @@ def prefix_config(cfg): return op + cfg +RE_MK_CONFIGS = re.compile('CONFIG_(\$\(SPL_(?:TPL_)?\))?([A-Za-z0-9_]*)') +RE_IFDEF = re.compile('(ifdef|ifndef)') +RE_C_CONFIGS = re.compile('CONFIG_([A-Za-z0-9_]*)') +RE_CONFIG_IS = re.compile('CONFIG_IS_ENABLED\(([A-Za-z0-9_]*)\)') + +class ConfigUse: + def __init__(self, cfg, is_spl, fname, rest): + self.cfg = cfg + self.is_spl = is_spl + self.fname = fname + self.rest = rest + + def __hash__(self): + return hash((self.cfg, self.is_spl)) + +def scan_makefiles(fnames): + """Scan Makefiles looking for Kconfig options + + Looks for uses of CONFIG options in Makefiles + + Args: + fnames (list of tuple): + str: Makefile filename where the option was found + str: Line of the Makefile + + Returns: + tuple: + dict: all_uses + key (ConfigUse): object + value (list of str): matching lines + dict: Uses by filename + key (str): filename + value (set of ConfigUse): uses in that filename + + >>> RE_MK_CONFIGS.search('CONFIG_FRED').groups() + (None, 'FRED') + >>> RE_MK_CONFIGS.search('CONFIG_$(SPL_)MARY').groups() + ('$(SPL_)', 'MARY') + >>> RE_MK_CONFIGS.search('CONFIG_$(SPL_TPL_)MARY').groups() + ('$(SPL_TPL_)', 'MARY') + """ + all_uses = collections.defaultdict(list) + fname_uses = {} + for fname, rest in fnames: + m_iter = RE_MK_CONFIGS.finditer(rest) + found = False + for m in m_iter: + found = True + real_opt = m.group(2) + if real_opt == '': + continue + is_spl = False + if m.group(1): + is_spl = True + use = ConfigUse(real_opt, is_spl, fname, rest) + if fname not in fname_uses: + fname_uses[fname] = set() + fname_uses[fname].add(use) + all_uses[use].append(rest) + return all_uses, fname_uses + + +def scan_src_files(fnames): + """Scan source files (other than Makefiles) looking for Kconfig options + + Looks for uses of CONFIG options + + Args: + fnames (list of tuple): + str: Makefile filename where the option was found + str: Line of the Makefile + + Returns: + tuple: + dict: all_uses + key (ConfigUse): object + value (list of str): matching lines + dict: Uses by filename + key (str): filename + value (set of ConfigUse): uses in that filename + + >>> RE_C_CONFIGS.search('CONFIG_FRED').groups() + ('FRED',) + >>> RE_CONFIG_IS.search('CONFIG_IS_ENABLED(MARY)').groups() + ('MARY',) + >>> RE_CONFIG_IS.search('#if CONFIG_IS_ENABLED(OF_PLATDATA)').groups() + ('OF_PLATDATA',) + """ + def add_uses(m_iter, is_spl): + for m in m_iter: + found = True + real_opt = m.group(1) + if real_opt == '': + continue + use = ConfigUse(real_opt, is_spl, fname, rest) + if fname not in fname_uses: + fname_uses[fname] = set() + fname_uses[fname].add(use) + all_uses[use].append(rest) + + all_uses = collections.defaultdict(list) + fname_uses = {} + for fname, rest in fnames: + m_iter = RE_C_CONFIGS.finditer(rest) + add_uses(m_iter, False) + + m_iter2 = RE_CONFIG_IS.finditer(rest) + add_uses(m_iter2, True) + + return all_uses, fname_uses + + +MODE_NORMAL, MODE_SPL, MODE_PROPER = range(3) + +def do_scan_source(path, do_update): + """Scan the source tree for Kconfig inconsistencies + + Args: + path (str): Path to source tree + do_update (bool) : True to write to scripts/kconf_... files + """ + def is_not_proper(name): + for prefix in SPL_PREFIXES: + if name.startswith(prefix): + return name[len(prefix):] + return False + + def check_not_found(all_uses, spl_mode): + """Check for Kconfig options mentioned in the source but not in Kconfig + + Args: + all_uses (dict): + key (ConfigUse): object + value (list of str): matching lines + spl_mode (int): If MODE_SPL, look at source code which implies + an SPL_ option, but for which there is none; + for MOD_PROPER, look at source code which implies a Proper + option (i.e. use of CONFIG_IS_ENABLED() or $(SPL_) or + $(SPL_TPL_) but for which there none; + if MODE_NORMAL, ignore SPL + + Returns: + dict: + key (str): CONFIG name (without 'CONFIG_' prefix + value (list of ConfigUse): List of uses of this CONFIG + """ + # Make sure we know about all the options + not_found = collections.defaultdict(list) + for use, rest in all_uses.items(): + name = use.cfg + if name in IGNORE_SYMS: + continue + check = True + + if spl_mode == MODE_SPL: + check = use.is_spl + + # If it is an SPL symbol, try prepending all SPL_ prefixes to + # find at least one SPL symbol + if use.is_spl: + add_to_dict = False + for prefix in SPL_PREFIXES: + try_name = prefix + name + sym = kconf.syms.get(try_name) + if sym: + break + if not sym: + not_found[f'SPL_{name}'].append(use) + continue + elif spl_mode == MODE_PROPER: + # Try to find the Proper version of this symbol, i.e. without + # the SPL_ prefix + proper_name = is_not_proper(name) + if proper_name: + name = proper_name + elif not use.is_spl: + check = False + else: # MODE_NORMAL + debug = False + sym = kconf.syms.get(name) + if not sym: + proper_name = is_not_proper(name) + if proper_name: + name = proper_name + sym = kconf.syms.get(name) + if not sym: + for prefix in SPL_PREFIXES: + try_name = prefix + name + sym = kconf.syms.get(try_name) + if sym: + break + if not sym: + not_found[name].append(use) + continue + + sym = kconf.syms.get(name) + if not sym and check: + not_found[name].append(use) + return not_found + + def show_uses(uses): + """Show a list of uses along with their filename and code snippet + + Args: + uses (dict): + key (str): CONFIG name (without 'CONFIG_' prefix + value (list of ConfigUse): List of uses of this CONFIG + """ + for name in sorted(uses): + print(f'{name}: ', end='') + for i, use in enumerate(uses[name]): + print(f'{" " if i else ""}{use.fname}: {use.rest.strip()}') + + + print('Scanning Kconfig') + kconf = KconfigScanner().conf + print(f'Scanning source in {path}') + args = ['git', 'grep', '-E', r'IS_ENABLED|\bCONFIG'] + with subprocess.Popen(args, stdout=subprocess.PIPE) as proc: + out, err = proc.communicate() + lines = out.splitlines() + re_fname = re.compile('^([^:]*):(.*)') + src_list = [] + mk_list = [] + for line in lines: + linestr = line.decode('utf-8') + m_fname = re_fname.search(linestr) + if not m_fname: + continue + fname, rest = m_fname.groups() + dirname, leaf = os.path.split(fname) + root, ext = os.path.splitext(leaf) + if ext == '.autoconf': + pass + elif ext in ['.c', '.h', '.S', '.lds', '.dts', '.dtsi', '.asl', '.cfg', + '.env', '.tmpl']: + src_list.append([fname, rest]) + elif 'Makefile' in root or ext == '.mk': + mk_list.append([fname, rest]) + elif ext in ['.yml', '.sh', '.py', '.awk', '.pl', '.rst', '', '.sed']: + pass + elif 'Kconfig' in root or 'Kbuild' in root: + pass + elif 'README' in root: + pass + elif dirname in ['configs']: + pass + elif dirname.startswith('doc') or dirname.startswith('scripts/kconfig'): + pass + else: + print(f'Not sure how to handle file {fname}') + + # Scan the Makefiles + all_uses, fname_uses = scan_makefiles(mk_list) + + spl_not_found = set() + proper_not_found = set() + + # Make sure we know about all the options + print('\nCONFIG options present in Makefiles but not Kconfig:') + not_found = check_not_found(all_uses, MODE_NORMAL) + show_uses(not_found) + + print('\nCONFIG options present in Makefiles but not Kconfig (SPL):') + not_found = check_not_found(all_uses, MODE_SPL) + show_uses(not_found) + spl_not_found |= set([is_not_proper(key) or key for key in not_found.keys()]) + + print('\nCONFIG options used as Proper in Makefiles but without a non-SPL_ variant:') + not_found = check_not_found(all_uses, MODE_PROPER) + show_uses(not_found) + proper_not_found |= set([key for key in not_found.keys()]) + + # Scan the source code + all_uses, fname_uses = scan_src_files(src_list) + + # Make sure we know about all the options + print('\nCONFIG options present in source but not Kconfig:') + not_found = check_not_found(all_uses, MODE_NORMAL) + show_uses(not_found) + + print('\nCONFIG options present in source but not Kconfig (SPL):') + not_found = check_not_found(all_uses, MODE_SPL) + show_uses(not_found) + spl_not_found |= set([is_not_proper(key) or key for key in not_found.keys()]) + + print('\nCONFIG options used as Proper in source but without a non-SPL_ variant:') + not_found = check_not_found(all_uses, MODE_PROPER) + show_uses(not_found) + proper_not_found |= set([key for key in not_found.keys()]) + + print('\nCONFIG options used as SPL but without an SPL_ variant:') + for item in sorted(spl_not_found): + print(f' {item}') + + print('\nCONFIG options used as Proper but without a non-SPL_ variant:') + for item in sorted(proper_not_found): + print(f' {item}') + + # Write out the updated information + if do_update: + with open(os.path.join(path, 'scripts', 'conf_nospl'), 'w') as out: + print('# These options should not be enabled in SPL builds\n', + file=out) + for item in sorted(spl_not_found): + print(item, file=out) + with open(os.path.join(path, 'scripts', 'conf_noproper'), 'w') as out: + print('# These options should not be enabled in Proper builds\n', + file=out) + for item in sorted(proper_not_found): + print(item, file=out) + + def main(): try: cpu_count = multiprocessing.cpu_count() @@ -1642,10 +1968,14 @@ doc/develop/moveconfig.rst for documentation.''' help='force sync by savedefconfig') parser.add_argument('-S', '--spl', action='store_true', default=False, help='parse config options defined for SPL build') + parser.add_argument('--scan-source', action='store_true', default=False, + help='scan source for uses of CONFIG options') parser.add_argument('-t', '--test', action='store_true', default=False, help='run unit tests') parser.add_argument('-y', '--yes', action='store_true', default=False, help="respond 'yes' to any prompts") + parser.add_argument('-u', '--update', action='store_true', default=False, + help="update scripts/ files (use with --scan-source)") parser.add_argument('-v', '--verbose', action='store_true', default=False, help='show any build errors as boards are built') parser.add_argument('configs', nargs='*') @@ -1660,6 +1990,10 @@ doc/develop/moveconfig.rst for documentation.''' return 1 unittest.main() + if args.scan_source: + do_scan_source(os.getcwd(), args.update) + return + if not any((len(configs), args.force_sync, args.build_db, args.imply, args.find)): parser.print_usage() -- cgit v1.2.3 From efabbe60d2391773eefd6ff900fc840e30339960 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Feb 2023 13:19:46 -0700 Subject: imx: Rename CONFIG_MXS to CFG_MXS This is not a Kconfig option so we should not be setting it in the Makefile. Rename it to use a CFS_ prefix, since this is still used in mxsimage.c In general tools should support all the features without reference to CONFIG options, but this is left to the maintainer to look at. Signed-off-by: Simon Glass --- tools/Makefile | 4 ++-- tools/mxsimage.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/Makefile b/tools/Makefile index edfa40903d9..2ee43dff542 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -158,9 +158,9 @@ fit_check_sign-objs := $(dumpimage-mkimage-objs) fit_check_sign.o file2include-objs := file2include.o ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_TOOLS_LIBCRYPTO),) -# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register +# Add CFG_MXS into host CFLAGS, so we can check whether or not register # the mxsimage support within tools/mxsimage.c . -HOSTCFLAGS_mxsimage.o += -DCONFIG_MXS +HOSTCFLAGS_mxsimage.o += -DCFG_MXS endif ifdef CONFIG_TOOLS_LIBCRYPTO diff --git a/tools/mxsimage.c b/tools/mxsimage.c index fee022aab46..fbe46c47fae 100644 --- a/tools/mxsimage.c +++ b/tools/mxsimage.c @@ -5,7 +5,7 @@ * Copyright (C) 2012-2013 Marek Vasut */ -#ifdef CONFIG_MXS +#ifdef CFG_MXS #include #include -- cgit v1.2.3 From aeca5194ce1a2d83246f3392ea8f665d35f799d0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Feb 2023 13:20:09 -0700 Subject: Drop ubsha1 tool This seems to have been used by ppc4xx which was removed a while back. The Kconfig does not exist so it is never built. Drop it. Signed-off-by: Simon Glass --- tools/.gitignore | 1 - tools/Makefile | 6 ---- tools/ubsha1.c | 83 -------------------------------------------------------- 3 files changed, 90 deletions(-) delete mode 100644 tools/ubsha1.c (limited to 'tools') diff --git a/tools/.gitignore b/tools/.gitignore index 28e8ce2a07a..788ea260a07 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -33,7 +33,6 @@ /relocate-rela /spl_size_limit /sunxi-spl-image-builder -/ubsha1 /update_octeon_header /version.h /xway-swap-bytes diff --git a/tools/Makefile b/tools/Makefile index 2ee43dff542..0eadd8154a7 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -29,7 +29,6 @@ CONFIG_CMD_LOADS = y CONFIG_CMD_NET = y CONFIG_XWAY_SWAP_BYTES = y CONFIG_NETCONSOLE = y -CONFIG_SHA1_CHECK_UB_IMG = y CONFIG_ARCH_SUNXI = y endif @@ -217,11 +216,6 @@ hostprogs-$(CONFIG_ARCH_SUNXI) += sunxi-spl-image-builder sunxi-spl-image-builder-objs := sunxi-spl-image-builder.o lib/bch.o hostprogs-$(CONFIG_NETCONSOLE) += ncb -hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1 - -ubsha1-objs := os_support.o ubsha1.o lib/sha1.o - -HOSTCFLAGS_ubsha1.o := -pedantic hostprogs-$(CONFIG_ARCH_KIRKWOOD) += kwboot hostprogs-$(CONFIG_ARCH_MVEBU) += kwboot diff --git a/tools/ubsha1.c b/tools/ubsha1.c deleted file mode 100644 index 90a6f3f59d2..00000000000 --- a/tools/ubsha1.c +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2007 - * Heiko Schocher, DENX Software Engineering, - */ - -#include "os_support.h" -#include -#include -#include -#include -#include -#include -#include -#include - -int main (int argc, char **argv) -{ - unsigned char output[20]; - int i, len; - - char *imagefile; - char *cmdname = *argv; - unsigned char *ptr; - unsigned char *data; - struct stat sbuf; - unsigned char *ptroff; - int ifd; - int off; - - if (argc > 1) { - imagefile = argv[1]; - ifd = open (imagefile, O_RDWR|O_BINARY); - if (ifd < 0) { - fprintf (stderr, "%s: Can't open %s: %s\n", - cmdname, imagefile, strerror(errno)); - exit (EXIT_FAILURE); - } - if (fstat (ifd, &sbuf) < 0) { - fprintf (stderr, "%s: Can't stat %s: %s\n", - cmdname, imagefile, strerror(errno)); - exit (EXIT_FAILURE); - } - len = sbuf.st_size; - ptr = (unsigned char *)mmap(0, len, - PROT_READ, MAP_SHARED, ifd, 0); - if (ptr == (unsigned char *)MAP_FAILED) { - fprintf (stderr, "%s: Can't read %s: %s\n", - cmdname, imagefile, strerror(errno)); - exit (EXIT_FAILURE); - } - - /* create a copy, so we can blank out the sha1 sum */ - data = malloc (len); - memcpy (data, ptr, len); - off = SHA1_SUM_POS; - ptroff = &data[len + off]; - for (i = 0; i < SHA1_SUM_LEN; i++) { - ptroff[i] = 0; - } - - sha1_csum ((unsigned char *) data, len, (unsigned char *)output); - - printf ("U-Boot sum:\n"); - for (i = 0; i < 20 ; i++) { - printf ("%02X ", output[i]); - } - printf ("\n"); - /* overwrite the sum in the bin file, with the actual */ - lseek (ifd, SHA1_SUM_POS, SEEK_END); - if (write (ifd, output, SHA1_SUM_LEN) != SHA1_SUM_LEN) { - fprintf (stderr, "%s: Can't write %s: %s\n", - cmdname, imagefile, strerror(errno)); - exit (EXIT_FAILURE); - } - - free (data); - (void) munmap((void *)ptr, len); - (void) close (ifd); - } - - return EXIT_SUCCESS; -} -- cgit v1.2.3 From b1dcc3355c7d2ab2f11ddaa4370422970543549a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 1 Feb 2023 13:20:25 -0700 Subject: tools: Drop xway-swap-bytes tool This is very old and does not appear to be used. The CONFIG option enabling it is no-longer present. Drop it. Signed-off-by: Simon Glass --- tools/Makefile | 4 ---- tools/xway-swap-bytes.c | 38 -------------------------------------- 2 files changed, 42 deletions(-) delete mode 100644 tools/xway-swap-bytes.c (limited to 'tools') diff --git a/tools/Makefile b/tools/Makefile index 0eadd8154a7..041c437e65b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -27,7 +27,6 @@ ifneq ($(HOST_TOOLS_ALL),) CONFIG_ARCH_KIRKWOOD = y CONFIG_CMD_LOADS = y CONFIG_CMD_NET = y -CONFIG_XWAY_SWAP_BYTES = y CONFIG_NETCONSOLE = y CONFIG_ARCH_SUNXI = y endif @@ -61,9 +60,6 @@ HOSTCFLAGS_gen_ethaddr_crc.o := -pedantic hostprogs-$(CONFIG_CMD_LOADS) += img2srec HOSTCFLAGS_img2srec.o := -pedantic -hostprogs-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes -HOSTCFLAGS_xway-swap-bytes.o := -pedantic - hostprogs-y += mkenvimage mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o diff --git a/tools/xway-swap-bytes.c b/tools/xway-swap-bytes.c deleted file mode 100644 index 3a6d82d54a0..00000000000 --- a/tools/xway-swap-bytes.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include - -#ifndef BUFSIZ -# define BUFSIZ 4096 -#endif - -#undef BUFSIZ -# define BUFSIZ 64 -int main (void) -{ - short ibuff[BUFSIZ], obuff[BUFSIZ]; - int rc, i, len; - - while ((rc = read (0, ibuff, sizeof (ibuff))) > 0) { - memset (obuff, 0, sizeof (obuff)); - for (i = 0; i < (rc + 1) / 2; i++) { - obuff[i] = ibuff[i ^ 1]; - } - - len = (rc + 1) & ~1; - - if (write (1, obuff, len) != len) { - perror ("read error"); - return (EXIT_FAILURE); - } - - memset (ibuff, 0, sizeof (ibuff)); - } - - if (rc < 0) { - perror ("read error"); - return (EXIT_FAILURE); - } - return (EXIT_SUCCESS); -} -- cgit v1.2.3