mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	 4e5b937a32
			
		
	
	
		4e5b937a32
		
	
	
	
	
		
			
			Based on 1 normalized pattern(s): this file is subject to the terms and conditions of the gnu general public license v2 extracted by the scancode license scanner the SPDX license identifier GPL-2.0-only has been chosen to replace the boilerplate/reference in 1 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Enrico Weigelt <info@metux.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190604081203.508532280@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
		
			
				
	
	
		
			1213 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1213 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env perl
 | |
| # SPDX-License-Identifier: GPL-2.0-only
 | |
| 
 | |
| # Copyright 2016 by Frank Rowand
 | |
| # Copyright 2016 by Gaurav Minocha
 | |
| #
 | |
| 
 | |
| use strict 'refs';
 | |
| use strict subs;
 | |
| 
 | |
| use Getopt::Long;
 | |
| 
 | |
| $VUFX = "160610a";
 | |
| 
 | |
| $script_name = $0;
 | |
| $script_name =~ s|^.*/||;
 | |
| 
 | |
| 
 | |
| # ----- constants for print_flags()
 | |
| 
 | |
| # Position in string $pr_flags.  Range of 0..($num_pr_flags - 1).
 | |
| $pr_flag_pos_mcompatible       = 0;
 | |
| $pr_flag_pos_driver            = 1;
 | |
| $pr_flag_pos_mdriver           = 2;
 | |
| $pr_flag_pos_config            = 3;
 | |
| $pr_flag_pos_mconfig           = 4;
 | |
| $pr_flag_pos_node_not_enabled  = 5;
 | |
| $pr_flag_pos_white_list        = 6;
 | |
| $pr_flag_pos_hard_coded        = 7;
 | |
| $pr_flag_pos_config_hard_coded = 8;
 | |
| $pr_flag_pos_config_none       = 9;
 | |
| $pr_flag_pos_config_m          = 10;
 | |
| $pr_flag_pos_config_y          = 11;
 | |
| $pr_flag_pos_config_test_fail  = 12;
 | |
| 
 | |
| $num_pr_flags = $pr_flag_pos_config_test_fail + 1;
 | |
| 
 | |
| # flags in @pr_flag_value must be unique values to allow simple regular
 | |
| # expessions to work for --include_flags and --exclude_flags.
 | |
| # Convention: use upper case letters for potential issues or problems.
 | |
| 
 | |
| @pr_flag_value = ('M', 'd', 'D', 'c', 'C', 'E', 'W', 'H', 'x', 'n', 'm', 'y', 'F');
 | |
| 
 | |
| @pr_flag_help = (
 | |
|     "multiple compatibles found for this node",
 | |
|     "driver found for this compatible",
 | |
|     "multiple drivers found for this compatible",
 | |
|     "kernel config found for this driver",
 | |
|     "multiple config options found for this driver",
 | |
|     "node is not enabled",
 | |
|     "compatible is white listed",
 | |
|     "matching driver and/or kernel config is hard coded",
 | |
|     "kernel config hard coded in Makefile",
 | |
|     "one or more kernel config file options is not set",
 | |
|     "one or more kernel config file options is set to 'm'",
 | |
|     "one or more kernel config file options is set to 'y'",
 | |
|     "one of more kernel config file options fails to have correct value"
 | |
| );
 | |
| 
 | |
| 
 | |
| # -----
 | |
| 
 | |
| %driver_config = ();   # driver config array, indexed by driver source file
 | |
| %driver_count = ();    # driver_cnt, indexed by compatible
 | |
| %compat_driver = ();   # compatible driver array, indexed by compatible
 | |
| %existing_config = (); # existing config symbols present in given config file
 | |
|                        # expected values are: "y", "m", a decimal number, a
 | |
|                        # hex number, or a string
 | |
| 
 | |
| # ----- magic compatibles, do not have a driver
 | |
| #
 | |
| # Will not search for drivers for these compatibles.
 | |
| 
 | |
| %compat_white_list = (
 | |
|        'none'                  => '1',
 | |
|        'pci'                   => '1',
 | |
|        'simple-bus'            => '1',
 | |
| );
 | |
| 
 | |
| # Will not search for drivers for these compatibles.
 | |
| #
 | |
| # These compatibles have a very large number of false positives.
 | |
| #
 | |
| # 'hardcoded_no_driver' is a magic value.  Other code knows this
 | |
| # magic value.  Do not use 'no_driver' here!
 | |
| #
 | |
| # Revisit each 'hardcoded_no_driver' to see how the compatible
 | |
| # is used.  Are there drivers that can be provided?
 | |
| 
 | |
| %driver_hard_code_list = (
 | |
|        'cache'                 => ['hardcoded_no_driver'],
 | |
|        'eeprom'                => ['hardcoded_no_driver'],
 | |
|        'gpio'                  => ['hardcoded_no_driver'],
 | |
|        'gpio-keys'             => ['drivers/input/keyboard/gpio_keys.c'],
 | |
|        'i2c-gpio'              => ['drivers/i2c/busses/i2c-gpio.c'],
 | |
|        'isa'                   => ['arch/mips/mti-malta/malta-dt.c',
 | |
|                                     'arch/x86/kernel/devicetree.c'],
 | |
|        'led'                   => ['hardcoded_no_driver'],
 | |
|        'm25p32'                => ['hardcoded_no_driver'],
 | |
|        'm25p64'                => ['hardcoded_no_driver'],
 | |
|        'm25p80'                => ['hardcoded_no_driver'],
 | |
|        'mtd-ram'               => ['drivers/mtd/maps/physmap_of.c'],
 | |
|        'pwm-backlight'         => ['drivers/video/backlight/pwm_bl.c'],
 | |
|        'spidev'                => ['hardcoded_no_driver'],
 | |
|        'syscon'                => ['drivers/mfd/syscon.c'],
 | |
|        'tlv320aic23'           => ['hardcoded_no_driver'],
 | |
|        'wm8731'                => ['hardcoded_no_driver'],
 | |
| );
 | |
| 
 | |
| # Use these config options instead of searching makefiles
 | |
| 
 | |
| %driver_config_hard_code_list = (
 | |
| 
 | |
|        # this one needed even if %driver_hard_code_list is empty
 | |
|        'no_driver'                             => ['no_config'],
 | |
|        'hardcoded_no_driver'                   => ['no_config'],
 | |
| 
 | |
|        # drivers/usb/host/ehci-ppc-of.c
 | |
|        # drivers/usb/host/ehci-xilinx-of.c
 | |
|        #  are included from:
 | |
|        #    drivers/usb/host/ehci-hcd.c
 | |
|        #  thus the search of Makefile for the included .c files is incorrect
 | |
|        # ehci-hcd.c wraps the includes with ifdef CONFIG_USB_EHCI_HCD_..._OF
 | |
|        #
 | |
|        # similar model for ohci-hcd.c (but no ohci-xilinx-of.c)
 | |
|        #
 | |
|        # similarly, uhci-hcd.c includes uhci-platform.c
 | |
| 
 | |
|        'drivers/usb/host/ehci-ppc-of.c'        => ['CONFIG_USB_EHCI_HCD',
 | |
|                                                    'CONFIG_USB_EHCI_HCD_PPC_OF'],
 | |
|        'drivers/usb/host/ohci-ppc-of.c'        => ['CONFIG_USB_OHCI_HCD',
 | |
|                                                    'CONFIG_USB_OHCI_HCD_PPC_OF'],
 | |
| 
 | |
|        'drivers/usb/host/ehci-xilinx-of.c'     => ['CONFIG_USB_EHCI_HCD',
 | |
|                                                    'CONFIG_USB_EHCI_HCD_XILINX'],
 | |
| 
 | |
|        'drivers/usb/host/uhci-platform.c'      => ['CONFIG_USB_UHCI_HCD',
 | |
|                                                    'CONFIG_USB_UHCI_PLATFORM'],
 | |
| 
 | |
|        # scan_makefile will find only one of these config options:
 | |
|        #    ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
 | |
|        'arch/arm/mach-imx/platsmp.c'           => ['CONFIG_SOC_IMX6 && CONFIG_SMP',
 | |
|                                                    'CONFIG_SOC_LS1021A && CONFIG_SMP'],
 | |
| );
 | |
| 
 | |
| 
 | |
| # 'virt/kvm/arm/.*' are controlled by makefiles in other directories,
 | |
| # using relative paths, such as 'KVM := ../../../virt/kvm'.  Do not
 | |
| # add complexity to find_kconfig() to deal with this.  There is a long
 | |
| # term intent to change the kvm related makefiles to the normal kernel
 | |
| # style.  After that is done, this entry can be removed from the
 | |
| # black_list_driver.
 | |
| 
 | |
| @black_list_driver = (
 | |
|        # kvm no longer a problem after commit 503a62862e8f in 4.7-rc1
 | |
|        # 'virt/kvm/arm/.*',
 | |
| );
 | |
| 
 | |
| 
 | |
| sub usage()
 | |
| {
 | |
|        print
 | |
| "
 | |
| Usage: $script_name [options] device-tree...
 | |
| 
 | |
|     device_tree is: dts_file | dtb_file | proc_device-tree
 | |
| 
 | |
| 
 | |
| Valid options:
 | |
|      -c FILE             Read kernel config options from FILE
 | |
|     --config FILE        synonym for 'c'
 | |
|     --config-format      config file friendly output format
 | |
|     --exclude-flag FLAG  exclude entries with a matching flag
 | |
|      -h                  Display this message and exit
 | |
|     --help               synonym for 'h'
 | |
|     --black-list-driver  use driver black list
 | |
|     --white-list-config  use config white list
 | |
|     --white-list-driver  use driver white list
 | |
|     --include-flag FLAG  include only entries with a matching flag
 | |
|     --include-suspect    include only entries with an uppercase flag
 | |
|     --short-name         do not show the path portion of the node name
 | |
|     --show-lists         report of white and black lists
 | |
|     --version            Display program version and exit
 | |
| 
 | |
| 
 | |
|   Report driver source files that match the compatibles in the device
 | |
|   tree file and the kernel config options that enable the driver source
 | |
|   files.
 | |
| 
 | |
|   This program must be run in the root directory of a Linux kernel
 | |
|   source tree.
 | |
| 
 | |
|   The default format is a report that is intended to be easily human
 | |
|   scannable.
 | |
| 
 | |
|   An alternate format can be selected by --config-format.  This will
 | |
|   create output that can easily be edited to create a fragment that can
 | |
|   be appended to the existing kernel config file.  Each entry consists of
 | |
|   multiple lines.  The first line reports flags, the node path, compatible
 | |
|   value, driver file matching the compatible, configuration options, and
 | |
|   current values of the configuration options.  For each configuration
 | |
|   option, the following lines report the current value and the value that
 | |
|   is required for the driver file to be included in the kernel.
 | |
| 
 | |
|   If a large number of drivers or config options is listed for a node,
 | |
|   and the '$pr_flag_value[$pr_flag_pos_hard_coded]' flag is set consider using --white-list-config and/or
 | |
|   --white-list-driver.  If the white list option suppresses the correct
 | |
|   entry please report that as a bug.
 | |
| 
 | |
|   CAUTION:
 | |
|      This program uses heuristics to guess which driver(s) support each
 | |
|      compatible string and which config option(s) enables the driver(s).
 | |
|      Do not believe that the reported information is fully correct.
 | |
|      This program is intended to aid the process of determining the
 | |
|      proper kernel configuration for a device tree, but this is not
 | |
|      a fully automated process -- human involvement may still be
 | |
|      required!
 | |
| 
 | |
|      The driver match heuristic used is to search for source files
 | |
|      containing the compatible string enclosed in quotes.
 | |
| 
 | |
|      This program might not be able to find all drivers matching a
 | |
|      compatible string.
 | |
| 
 | |
|      Some makefiles are overly clever.  This program was not made
 | |
|      complex enough to handle them.  If no config option is listed
 | |
|      for a driver, look at the makefile for the driver source file.
 | |
|      Even if a config option is listed for a driver, some other
 | |
|      available config options may not be listed.
 | |
| 
 | |
|   FLAG values:
 | |
| ";
 | |
| 
 | |
|        for ($k = 0; $k < $num_pr_flags; $k++) {
 | |
|                printf "     %s   %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
 | |
|        }
 | |
| 
 | |
|        print
 | |
| "
 | |
|      Upper case letters indicate potential issues or problems.
 | |
| 
 | |
|   The flag:
 | |
| 
 | |
| ";
 | |
| 
 | |
|        $k = $pr_flag_pos_hard_coded;
 | |
|        printf "     %s   %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
 | |
| 
 | |
|        print
 | |
| "
 | |
|   will be set if the config or driver is in the white lists, even if
 | |
|   --white-list-config and --white-list-driver are not specified.
 | |
|   This is a hint that 1) many of these reported lines are likely to
 | |
|   be incorrect, and 2) using those options will reduce the number of
 | |
|   drivers and/or config options reported.
 | |
| 
 | |
|   --white-list-config and --white-list-driver may not be accurate if this
 | |
|   program is not well maintained.  Use them with appropriate skepticism.
 | |
|   Use the --show-lists option to report the values in the list.
 | |
| 
 | |
|   Return value:
 | |
|     0   if no error
 | |
|     1   error processing command line
 | |
|     2   unable to open or read kernel config file
 | |
|     3   unable to open or process input device tree file(s)
 | |
| 
 | |
|   EXAMPLES:
 | |
| 
 | |
|      dt_to_config arch/arm/boot/dts/my_dts_file.dts
 | |
| 
 | |
|        Basic report.
 | |
| 
 | |
|      dt_to_config \\
 | |
|         --config \${KBUILD_OUTPUT}/.config \\
 | |
|         arch/\${ARCH}/boot/dts/my_dts_file.dts
 | |
| 
 | |
|        Full report, with config file issues noted.
 | |
| 
 | |
|      dt_to_config --include-suspect \\
 | |
|         --config \${KBUILD_OUTPUT}/.config \\
 | |
|         arch/\${ARCH}/boot/dts/my_dts_file.dts
 | |
| 
 | |
|        Report of node / compatible string / driver tuples that should
 | |
|        be further investigated.  A node may have multiple compatible
 | |
|        strings.  A compatible string may be matched by multiple drivers.
 | |
|        A driver may have config file issues noted.  The compatible string
 | |
|        and/or driver may be in the white lists.
 | |
| 
 | |
|      dt_to_config --include-suspect --config-format \\
 | |
|         --config ${KBUILD_OUTPUT}/.config \\
 | |
|         arch/\${ARCH}/boot/dts/my_dts_file.dts
 | |
| 
 | |
|        Report of node / compatible string / driver tuples that should
 | |
|        be further investigated.  The report can be edited to uncomment
 | |
|        the config options to select the desired tuple for a given node.
 | |
|        A node may have multiple compatible strings.  A compatible string
 | |
|        may be matched by multiple drivers.  A driver may have config file
 | |
|        issues noted.  The compatible string and/or driver may be in the
 | |
|        white lists.
 | |
| 
 | |
| ";
 | |
| }
 | |
| 
 | |
| sub set_flag()
 | |
| {
 | |
|        # pr_flags_ref is a reference to $pr_flags
 | |
| 
 | |
|        my $pr_flags_ref = shift;
 | |
|        my $pos          = shift;
 | |
| 
 | |
|        substr $$pr_flags_ref, $pos, 1, $pr_flag_value[$pos];
 | |
| 
 | |
|        return $pr_flags;
 | |
| }
 | |
| 
 | |
| sub print_flags()
 | |
| {
 | |
|        # return 1 if anything printed, else 0
 | |
| 
 | |
|        # some fields of pn_arg_ref might not be used in this function, but
 | |
|        # extract all of them anyway.
 | |
|        my $pn_arg_ref     = shift;
 | |
| 
 | |
|        my $compat         = $pn_arg_ref->{compat};
 | |
|        my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
 | |
|        my $config         = $pn_arg_ref->{config};
 | |
|        my $config_cnt     = $pn_arg_ref->{config_cnt};
 | |
|        my $driver         = $pn_arg_ref->{driver};
 | |
|        my $driver_cnt     = $pn_arg_ref->{driver_cnt};
 | |
|        my $full_node      = $pn_arg_ref->{full_node};
 | |
|        my $node           = $pn_arg_ref->{node};
 | |
|        my $node_enabled   = $pn_arg_ref->{node_enabled};
 | |
|        my $white_list     = $pn_arg_ref->{white_list};
 | |
| 
 | |
|        my $pr_flags       = '-' x $num_pr_flags;
 | |
| 
 | |
| 
 | |
|        # ----- set flags in $pr_flags
 | |
| 
 | |
|        if ($compatible_cnt > 1) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_mcompatible);
 | |
|        }
 | |
| 
 | |
|        if ($config_cnt > 1) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_mconfig);
 | |
|        }
 | |
| 
 | |
|        if ($driver_cnt >= 1) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_driver);
 | |
|        }
 | |
| 
 | |
|        if ($driver_cnt > 1) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_mdriver);
 | |
|        }
 | |
| 
 | |
|        # These strings are the same way the linux kernel tests.
 | |
|        # The ePapr lists of values is slightly different.
 | |
|        if (!(
 | |
|              ($node_enabled eq "") ||
 | |
|              ($node_enabled eq "ok") ||
 | |
|              ($node_enabled eq "okay")
 | |
|             )) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_node_not_enabled);
 | |
|        }
 | |
| 
 | |
|        if ($white_list) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_white_list);
 | |
|        }
 | |
| 
 | |
|        if (exists($driver_hard_code_list{$compat}) ||
 | |
|            (exists($driver_config_hard_code_list{$driver}) &&
 | |
|             ($driver ne "no_driver"))) {
 | |
|                &set_flag(\$pr_flags, $pr_flag_pos_hard_coded);
 | |
|        }
 | |
| 
 | |
|        my @configs = split(' && ', $config);
 | |
|        for $configs (@configs) {
 | |
|                $not = $configs =~ /^!/;
 | |
|                $configs =~ s/^!//;
 | |
| 
 | |
|                if (($configs ne "no_config") && ($configs ne "no_makefile")) {
 | |
|                        &set_flag(\$pr_flags, $pr_flag_pos_config);
 | |
|                }
 | |
| 
 | |
|                if (($config_cnt >= 1) &&
 | |
|                    ($configs !~ /CONFIG_/) &&
 | |
|                    (($configs ne "no_config") && ($configs ne "no_makefile"))) {
 | |
|                        &set_flag(\$pr_flags, $pr_flag_pos_config_hard_coded);
 | |
|                }
 | |
| 
 | |
|                my $existing_config = $existing_config{$configs};
 | |
|                if ($existing_config eq "m") {
 | |
|                        &set_flag(\$pr_flags, $pr_flag_pos_config_m);
 | |
|                        # Possible fail, depends on whether built in or
 | |
|                        # module is desired.
 | |
|                        &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
 | |
|                } elsif ($existing_config eq "y") {
 | |
|                        &set_flag(\$pr_flags, $pr_flag_pos_config_y);
 | |
|                        if ($not) {
 | |
|                                &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
 | |
|                        }
 | |
|                } elsif (($config_file) && ($configs =~ /CONFIG_/)) {
 | |
|                        &set_flag(\$pr_flags, $pr_flag_pos_config_none);
 | |
|                        if (!$not) {
 | |
|                                &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
 | |
|                        }
 | |
|                }
 | |
|        }
 | |
| 
 | |
|        # ----- include / exclude filters
 | |
| 
 | |
|        if ($include_flag_pattern && ($pr_flags !~ m/$include_flag_pattern/)) {
 | |
|                return 0;
 | |
|        }
 | |
| 
 | |
|        if ($exclude_flag_pattern && ($pr_flags =~ m/$exclude_flag_pattern/)) {
 | |
|                return 0;
 | |
|        }
 | |
| 
 | |
|        if ($config_format) {
 | |
|                print "# ";
 | |
|        }
 | |
|        print "$pr_flags : ";
 | |
| 
 | |
|        return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub print_node()
 | |
| {
 | |
|        # return number of lines printed
 | |
| 
 | |
|        # some fields of pn_arg_ref might not be used in this function, but
 | |
|        # extract all of them anyway.
 | |
|        my $pn_arg_ref     = shift;
 | |
| 
 | |
|        my $compat         = $pn_arg_ref->{compat};
 | |
|        my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
 | |
|        my $config         = $pn_arg_ref->{config};
 | |
|        my $config_cnt     = $pn_arg_ref->{config_cnt};
 | |
|        my $driver         = $pn_arg_ref->{driver};
 | |
|        my $driver_cnt     = $pn_arg_ref->{driver_cnt};
 | |
|        my $full_node      = $pn_arg_ref->{full_node};
 | |
|        my $node           = $pn_arg_ref->{node};
 | |
|        my $node_enabled   = $pn_arg_ref->{node_enabled};
 | |
|        my $white_list     = $pn_arg_ref->{white_list};
 | |
| 
 | |
|        my $separator;
 | |
| 
 | |
|        if (! &print_flags($pn_arg_ref)) {
 | |
|                return 0;
 | |
|        }
 | |
| 
 | |
| 
 | |
|        if ($short_name) {
 | |
|                print "$node";
 | |
|        } else {
 | |
|                print "$full_node";
 | |
|        }
 | |
|        print " : $compat : $driver : $config : ";
 | |
| 
 | |
|        my @configs = split(' && ', $config);
 | |
| 
 | |
|        if ($config_file) {
 | |
|                for $configs (@configs) {
 | |
|                        $configs =~ s/^!//;
 | |
|                        my $existing_config = $existing_config{$configs};
 | |
|                        if (!$existing_config) {
 | |
|                                # check for /-m/, /-y/, or /-objs/
 | |
|                                if ($configs !~ /CONFIG_/) {
 | |
|                                        $existing_config = "x";
 | |
|                                };
 | |
|                        };
 | |
|                        if ($existing_config) {
 | |
|                                print "$separator", "$existing_config";
 | |
|                                $separator = ", ";
 | |
|                        } else {
 | |
|                                print "$separator", "n";
 | |
|                                $separator = ", ";
 | |
|                        }
 | |
|                }
 | |
|        } else {
 | |
|                print "none";
 | |
|        }
 | |
| 
 | |
|        print "\n";
 | |
| 
 | |
|        if ($config_format) {
 | |
|                for $configs (@configs) {
 | |
|                        $not = $configs =~ /^!/;
 | |
|                        $configs =~ s/^!//;
 | |
|                        my $existing_config = $existing_config{$configs};
 | |
| 
 | |
|                        if ($not) {
 | |
|                                if ($configs !~ /CONFIG_/) {
 | |
|                                        print "# $configs\n";
 | |
|                                } elsif ($existing_config eq "m") {
 | |
|                                        print "# $configs is m\n";
 | |
|                                        print "# $configs=n\n";
 | |
|                                } elsif ($existing_config eq "y") {
 | |
|                                        print "# $configs is set\n";
 | |
|                                        print "# $configs=n\n";
 | |
|                                } else {
 | |
|                                        print "# $configs is not set\n";
 | |
|                                        print "# $configs=n\n";
 | |
|                                }
 | |
| 
 | |
|                        } else {
 | |
|                                if ($configs !~ /CONFIG_/) {
 | |
|                                        print "# $configs\n";
 | |
|                                } elsif ($existing_config eq "m") {
 | |
|                                        print "# $configs is m\n";
 | |
|                                        print "# $configs=y\n";
 | |
|                                } elsif ($existing_config eq "y") {
 | |
|                                        print "# $configs is set\n";
 | |
|                                        print "# $configs=y\n";
 | |
|                                } else {
 | |
|                                        print "# $configs is not set\n";
 | |
|                                        print "# $configs=y\n";
 | |
|                                }
 | |
|                        }
 | |
|                }
 | |
|        }
 | |
| 
 | |
|        return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub scan_makefile
 | |
| {
 | |
|        my $pn_arg_ref    = shift;
 | |
|        my $driver        = shift;
 | |
| 
 | |
|        # ----- Find Kconfig symbols that enable driver
 | |
| 
 | |
|        my ($dir, $base) = $driver =~ m{(.*)/(.*).c};
 | |
| 
 | |
|        my $makefile = $dir . "/Makefile";
 | |
|        if (! -r $makefile) {
 | |
|                $makefile = $dir . "/Kbuild";
 | |
|        }
 | |
|        if (! -r $makefile) {
 | |
|                my $config;
 | |
| 
 | |
|                $config = 'no_makefile';
 | |
|                push @{ $driver_config{$driver} }, $config;
 | |
|                return;
 | |
|        }
 | |
| 
 | |
|        if (!open(MAKEFILE_FILE, "<", "$makefile")) {
 | |
|                return;
 | |
|        }
 | |
| 
 | |
|        my $line;
 | |
|        my @config;
 | |
|        my @if_config;
 | |
|        my @make_var;
 | |
| 
 | |
|        NEXT_LINE:
 | |
|        while ($next_line = <MAKEFILE_FILE>) {
 | |
|                my $config;
 | |
|                my $if_config;
 | |
|                my $ifdef;
 | |
|                my $ifeq;
 | |
|                my $ifndef;
 | |
|                my $ifneq;
 | |
|                my $ifdef_config;
 | |
|                my $ifeq_config;
 | |
|                my $ifndef_config;
 | |
|                my $ifneq_config;
 | |
| 
 | |
|                chomp($next_line);
 | |
|                $line = $line . $next_line;
 | |
|                if ($next_line =~ /\\$/) {
 | |
|                        $line =~ s/\\$/ /;
 | |
|                        next NEXT_LINE;
 | |
|                }
 | |
|                if ($line =~ /^\s*#/) {
 | |
|                        $line = "";
 | |
|                        next NEXT_LINE;
 | |
|                }
 | |
| 
 | |
|                # -----  condition ... else ... endif
 | |
| 
 | |
|                if ($line =~ /^([ ]\s*|)else\b/) {
 | |
|                        $if_config = "!" . pop @if_config;
 | |
|                        $if_config =~ s/^!!//;
 | |
|                        push @if_config, $if_config;
 | |
|                        $line =~ s/^([ ]\s*|)else\b//;
 | |
|                }
 | |
| 
 | |
|                ($null, $ifeq_config,  $ifeq_config_val )  = $line =~ /^([ ]\s*|)ifeq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
 | |
|                ($null, $ifneq_config, $ifneq_config_val)  = $line =~ /^([ ]\s*|)ifneq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
 | |
|                ($null, $ifdef_config)                     = $line =~ /^([ ]\s*|)ifdef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
 | |
|                ($null, $ifndef_config)                    = $line =~ /^([ ]\s*|)ifndef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
 | |
| 
 | |
|                ($null, $ifeq)   = $line =~ /^([ ]\s*|)ifeq\b\s*(.*)/;
 | |
|                ($null, $ifneq)  = $line =~ /^([ ]\s*|)ifneq\b\s*(.*)/;
 | |
|                ($null, $ifdef)  = $line =~ /^([ ]\s*|)ifdef\b\s*(.*)/;
 | |
|                ($null, $ifndef) = $line =~ /^([ ]\s*|)ifndef\b\s*(.*)/;
 | |
| 
 | |
|                # Order of tests is important.  Prefer "CONFIG_*" regex match over
 | |
|                # less specific regex match.
 | |
|                if ($ifdef_config) {
 | |
|                        $if_config = $ifdef_config;
 | |
|                } elsif ($ifeq_config) {
 | |
|                        if ($ifeq_config_val =~ /y/) {
 | |
|                                $if_config = $ifeq_config;
 | |
|                        } else {
 | |
|                                $if_config = "!" . $ifeq_config;
 | |
|                        }
 | |
|                } elsif ($ifndef_config) {
 | |
|                        $if_config = "!" . $ifndef_config;
 | |
|                } elsif ($ifneq_config) {
 | |
|                        if ($ifneq_config_val =~ /y/) {
 | |
|                                $if_config = "!" . $ifneq_config;
 | |
|                        } else {
 | |
|                                $if_config = $ifneq_config;
 | |
|                        }
 | |
|                } elsif ($ifdef) {
 | |
|                        $if_config = $ifdef;
 | |
|                } elsif ($ifeq) {
 | |
|                        $if_config = $ifeq;
 | |
|                } elsif ($ifndef) {
 | |
|                        $if_config = "!" . $ifndef;
 | |
|                } elsif ($ifneq) {
 | |
|                        $if_config = "!" . $ifneq;
 | |
|                } else {
 | |
|                        $if_config = "";
 | |
|                }
 | |
|                $if_config =~ s/^!!//;
 | |
| 
 | |
|                if ($if_config) {
 | |
|                        push @if_config, $if_config;
 | |
|                        $line = "";
 | |
|                        next NEXT_LINE;
 | |
|                }
 | |
| 
 | |
|                if ($line =~ /^([ ]\s*|)endif\b/) {
 | |
|                        pop @if_config;
 | |
|                        $line = "";
 | |
|                        next NEXT_LINE;
 | |
|                }
 | |
| 
 | |
|                # ----- simple CONFIG_* = *.[co]  or  xxx [+:?]*= *.[co]
 | |
|                # Most makefiles select on *.o, but
 | |
|                # arch/powerpc/boot/Makefile selects on *.c
 | |
| 
 | |
|                ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$base.[co]\b/;
 | |
| 
 | |
|                # ----- match a make variable instead of *.[co]
 | |
|                # Recursively expanded variables are not handled.
 | |
| 
 | |
|                if (!$config) {
 | |
|                        my $make_var;
 | |
|                        ($make_var) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$base.[co]\b/;
 | |
|                        if ($make_var) {
 | |
|                                if ($make_var =~ /[a-zA-Z0-9]+-[ym]/) {
 | |
|                                        $config = $make_var;
 | |
|                                } elsif ($make_var =~ /[a-zA-Z0-9]+-objs/) {
 | |
|                                        $config = $make_var;
 | |
|                                } else {
 | |
|                                        push @make_var, $make_var;
 | |
|                                }
 | |
|                        }
 | |
|                }
 | |
| 
 | |
|                if (!$config) {
 | |
|                        for $make_var (@make_var) {
 | |
|                                ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$make_var\b/;
 | |
|                                last if ($config);
 | |
|                        }
 | |
|                }
 | |
| 
 | |
|                if (!$config) {
 | |
|                        for $make_var (@make_var) {
 | |
|                                ($config) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$make_var\b/;
 | |
|                                last if ($config);
 | |
|                        }
 | |
|                }
 | |
| 
 | |
|                # ----- next if no config found
 | |
| 
 | |
|                if (!$config) {
 | |
|                        $line = "";
 | |
|                        next NEXT_LINE;
 | |
|                }
 | |
| 
 | |
|                for $if_config (@if_config) {
 | |
|                        $config = $if_config . " && " . $config;
 | |
|                }
 | |
| 
 | |
|                push @{ $driver_config{$driver} }, $config;
 | |
| 
 | |
|                $line = "";
 | |
|        }
 | |
| 
 | |
|        close(MAKEFILE_FILE);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| sub find_kconfig
 | |
| {
 | |
|        my $pn_arg_ref    = shift;
 | |
|        my $driver        = shift;
 | |
| 
 | |
|        my $lines_printed = 0;
 | |
|        my @configs;
 | |
| 
 | |
|        if (!@{ $driver_config{$driver} }) {
 | |
|                &scan_makefile($pn_arg_ref, $driver);
 | |
|                if (!@{ $driver_config{$driver} }) {
 | |
|                        push @{ $driver_config{$driver} }, "no_config";
 | |
|                }
 | |
|        }
 | |
| 
 | |
|        @configs = @{ $driver_config{$driver} };
 | |
| 
 | |
|        $$pn_arg_ref{config_cnt} = $#configs + 1;
 | |
|        for my $config (@configs) {
 | |
|                $$pn_arg_ref{config} = $config;
 | |
|                $lines_printed += &print_node($pn_arg_ref);
 | |
|        }
 | |
| 
 | |
|        return $lines_printed;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub handle_compatible()
 | |
| {
 | |
|        my $full_node     = shift;
 | |
|        my $node          = shift;
 | |
|        my $compatible    = shift;
 | |
|        my $node_enabled  = shift;
 | |
| 
 | |
|        my $compat;
 | |
|        my $lines_printed = 0;
 | |
|        my %pn_arg        = ();
 | |
| 
 | |
|        return if (!$node or !$compatible);
 | |
| 
 | |
|        # Do not process compatible property of root node,
 | |
|        # it is used to match board, not to bind a driver.
 | |
|        return if ($node eq "/");
 | |
| 
 | |
|        $pn_arg{full_node}    = $full_node;
 | |
|        $pn_arg{node}         = $node;
 | |
|        $pn_arg{node_enabled} = $node_enabled;
 | |
| 
 | |
|        my @compatibles = split('", "', $compatible);
 | |
| 
 | |
|        $compatibles[0] =~ s/^"//;
 | |
|        $compatibles[$#compatibles] =~ s/"$//;
 | |
| 
 | |
|        $pn_arg{compatible_cnt} = $#compatibles + 1;
 | |
| 
 | |
|        COMPAT:
 | |
|        for $compat (@compatibles) {
 | |
| 
 | |
|                $pn_arg{compat}     = $compat;
 | |
|                $pn_arg{driver_cnt} = 0;
 | |
|                $pn_arg{white_list} = 0;
 | |
| 
 | |
|                if (exists($compat_white_list{$compat})) {
 | |
|                        $pn_arg{white_list} = 1;
 | |
|                        $pn_arg{driver}     = "no_driver";
 | |
|                        $pn_arg{config_cnt} = 1;
 | |
|                        $pn_arg{config}     = "no_config";
 | |
|                        $lines_printed += &print_node(\%pn_arg);
 | |
|                        next COMPAT;
 | |
|                }
 | |
| 
 | |
|                # ----- if compat previously seen, use cached info
 | |
| 
 | |
|                if (exists($compat_driver{$compat})) {
 | |
|                        for my $driver (@{ $compat_driver{$compat} }) {
 | |
|                                $pn_arg{driver}     = $driver;
 | |
|                                $pn_arg{driver_cnt} = $driver_count{$compat};
 | |
|                                $pn_arg{config_cnt} = $#{ $driver_config{$driver}} + 1;
 | |
| 
 | |
|                                for my $config (@{ $driver_config{$driver} }) {
 | |
|                                        $pn_arg{config} = $config;
 | |
|                                        $lines_printed += &print_node(\%pn_arg);
 | |
|                                }
 | |
| 
 | |
|                                if (!@{ $driver_config{$driver} }) {
 | |
|                                        # no config cached yet
 | |
|                                        # $driver in %driver_hard_code_list
 | |
|                                        # but not %driver_config_hard_code_list
 | |
|                                        $lines_printed += &find_kconfig(\%pn_arg, $driver);
 | |
|                                }
 | |
|                        }
 | |
|                        next COMPAT;
 | |
|                }
 | |
| 
 | |
| 
 | |
|                # ----- Find drivers (source files that contain compatible)
 | |
| 
 | |
|                # this will miss arch/sparc/include/asm/parport.h
 | |
|                # It is better to move the compatible out of the .h
 | |
|                # than to add *.h. to the files list, because *.h generates
 | |
|                # a lot of false negatives.
 | |
|                my $files = '"*.c"';
 | |
|                my $drivers = `git grep -l '"$compat"' -- $files`;
 | |
|                chomp($drivers);
 | |
|                if ($drivers eq "") {
 | |
|                        $pn_arg{driver} = "no_driver";
 | |
|                        $pn_arg{config_cnt} = 1;
 | |
|                        $pn_arg{config} = "no_config";
 | |
|                        push @{ $compat_driver{$compat} }, "no_driver";
 | |
|                        $lines_printed += &print_node(\%pn_arg);
 | |
|                        next COMPAT;
 | |
|                }
 | |
| 
 | |
|                my @drivers = split("\n", $drivers);
 | |
|                $driver_count{$compat} = $#drivers + 1;
 | |
|                $pn_arg{driver_cnt}    = $#drivers + 1;
 | |
| 
 | |
|                DRIVER:
 | |
|                for my $driver (@drivers) {
 | |
|                        push @{ $compat_driver{$compat} }, $driver;
 | |
|                        $pn_arg{driver} = $driver;
 | |
| 
 | |
|                        # ----- if driver previously seen, use cached info
 | |
| 
 | |
|                        $pn_arg{config_cnt} = $#{ $driver_config{$driver} } + 1;
 | |
|                        for my $config (@{ $driver_config{$driver} }) {
 | |
|                                $pn_arg{config} = $config;
 | |
|                                $lines_printed += &print_node(\%pn_arg);
 | |
|                        }
 | |
|                        if (@{ $driver_config{$driver} }) {
 | |
|                                next DRIVER;
 | |
|                        }
 | |
| 
 | |
|                        if ($black_list_driver) {
 | |
|                                for $black (@black_list_driver) {
 | |
|                                        next DRIVER if ($driver =~ /^$black$/);
 | |
|                                }
 | |
|                        }
 | |
| 
 | |
| 
 | |
|                        # ----- Find Kconfig symbols that enable driver
 | |
| 
 | |
|                        $lines_printed += &find_kconfig(\%pn_arg, $driver);
 | |
| 
 | |
|                }
 | |
|        }
 | |
| 
 | |
|        # White space (line) between nodes for readability.
 | |
|        # Each node may report several compatibles.
 | |
|        # For each compatible, multiple drivers may be reported.
 | |
|        # For each driver, multiple CONFIG_ options may be reported.
 | |
|        if ($lines_printed) {
 | |
|                print "\n";
 | |
|        }
 | |
| }
 | |
| 
 | |
| sub read_dts()
 | |
| {
 | |
|        my $file         = shift;
 | |
| 
 | |
|        my $compatible   = "";
 | |
|        my $line;
 | |
|        my $node         = "";
 | |
|        my $node_enabled = "";
 | |
| 
 | |
|        if (! -r $file) {
 | |
|                print STDERR "file '$file' is not readable or does not exist\n";
 | |
|                exit 3;
 | |
|        }
 | |
| 
 | |
|        if (!open(DT_FILE, "-|", "$dtx_diff $file")) {
 | |
|                print STDERR "\n";
 | |
|                print STDERR "shell command failed:\n";
 | |
|                print STDERR "   $dtx_diff $file\n";
 | |
|                print STDERR "\n";
 | |
|                exit 3;
 | |
|        }
 | |
| 
 | |
|        FILE:
 | |
|        while ($line = <DT_FILE>) {
 | |
|                chomp($line);
 | |
| 
 | |
|                if ($line =~ /{/) {
 | |
| 
 | |
|                        &handle_compatible($full_node, $node, $compatible,
 | |
|                                           $node_enabled);
 | |
| 
 | |
|                        while ($end_node_count-- > 0) {
 | |
|                                pop @full_node;
 | |
|                        };
 | |
|                        $end_node_count = 0;
 | |
|                        $full_node = @full_node[-1];
 | |
| 
 | |
|                        $node = $line;
 | |
|                        $node =~ s/^\s*(.*)\s+\{.*/$1/;
 | |
|                        $node =~ s/.*: //;
 | |
|                        if ($node eq '/' ) {
 | |
|                                $full_node = '/';
 | |
|                        } elsif ($full_node ne '/') {
 | |
|                                $full_node = $full_node . '/' . $node;
 | |
|                        } else {
 | |
|                                $full_node = '/' . $node;
 | |
|                        }
 | |
|                        push @full_node, $full_node;
 | |
| 
 | |
|                        $compatible = "";
 | |
|                        $node_enabled = "";
 | |
|                        next FILE;
 | |
|                }
 | |
| 
 | |
|                if ($line =~ /}/) {
 | |
|                        $end_node_count++;
 | |
|                }
 | |
| 
 | |
|                if ($line =~ /(\s+|^)status =/) {
 | |
|                        $node_enabled = $line;
 | |
|                        $node_enabled =~ s/^\t*//;
 | |
|                        $node_enabled =~ s/^status = "//;
 | |
|                        $node_enabled =~ s/";$//;
 | |
|                        next FILE;
 | |
|                }
 | |
| 
 | |
|                if ($line =~ /(\s+|^)compatible =/) {
 | |
|                        # Extract all compatible entries for this device
 | |
|                        # White space matching here and in handle_compatible() is
 | |
|                        # precise, because input format is the output of dtc,
 | |
|                        # which is invoked by dtx_diff.
 | |
|                        $compatible = $line;
 | |
|                        $compatible =~ s/^\t*//;
 | |
|                        $compatible =~ s/^compatible = //;
 | |
|                        $compatible =~ s/;$//;
 | |
|                }
 | |
|        }
 | |
| 
 | |
|        &handle_compatible($full_node, $node, $compatible, $node_enabled);
 | |
| 
 | |
|        close(DT_FILE);
 | |
| }
 | |
| 
 | |
| 
 | |
| sub read_config_file()
 | |
| {
 | |
|        if (! -r $config_file) {
 | |
|                print STDERR "file '$config_file' is not readable or does not exist\n";
 | |
|                exit 2;
 | |
|        }
 | |
| 
 | |
|        if (!open(CONFIG_FILE, "<", "$config_file")) {
 | |
|                print STDERR "open $config_file failed\n";
 | |
|                exit 2;
 | |
|        }
 | |
| 
 | |
|        my @line;
 | |
| 
 | |
|        LINE:
 | |
|        while ($line = <CONFIG_FILE>) {
 | |
|                chomp($line);
 | |
|                next LINE if ($line =~ /^\s*#/);
 | |
|                next LINE if ($line =~ /^\s*$/);
 | |
|                @line = split /=/, $line;
 | |
|                $existing_config{@line[0]} = @line[1];
 | |
|        }
 | |
| 
 | |
|        close(CONFIG_FILE);
 | |
| }
 | |
| 
 | |
| 
 | |
| sub cmd_line_err()
 | |
| {
 | |
|        my $msg = shift;
 | |
| 
 | |
|        print STDERR "\n";
 | |
|        print STDERR "   ERROR processing command line options\n";
 | |
|        print STDERR "         $msg\n" if ($msg ne "");
 | |
|        print STDERR "\n";
 | |
|        print STDERR "   For help, type '$script_name --help'\n";
 | |
|        print STDERR "\n";
 | |
| }
 | |
| 
 | |
| 
 | |
| # -----------------------------------------------------------------------------
 | |
| # program entry point
 | |
| 
 | |
| Getopt::Long::Configure("no_ignore_case", "bundling");
 | |
| 
 | |
| if (!GetOptions(
 | |
|        "c=s"               => \$config_file,
 | |
|        "config=s"          => \$config_file,
 | |
|        "config-format"     => \$config_format,
 | |
|        "exclude-flag=s"    => \@exclude_flag,
 | |
|        "h"                 => \$help,
 | |
|        "help"              => \$help,
 | |
|        "black-list-driver" => \$black_list_driver,
 | |
|        "white-list-config" => \$white_list_config,
 | |
|        "white-list-driver" => \$white_list_driver,
 | |
|        "include-flag=s"    => \@include_flag,
 | |
|        "include-suspect"   => \$include_suspect,
 | |
|        "short-name"        => \$short_name,
 | |
|        "show-lists"        => \$show_lists,
 | |
|        "version"           => \$version,
 | |
|        )) {
 | |
| 
 | |
|        &cmd_line_err();
 | |
| 
 | |
|        exit 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| my $exit_after_messages = 0;
 | |
| 
 | |
| if ($version) {
 | |
|        print STDERR "\n$script_name  $VUFX\n\n";
 | |
|        $exit_after_messages = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| if ($help) {
 | |
|        &usage;
 | |
|        $exit_after_messages = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| if ($show_lists) {
 | |
| 
 | |
|        print "\n";
 | |
|        print "These compatibles are hard coded to have no driver.\n";
 | |
|        print "\n";
 | |
|        for my $compat (sort keys %compat_white_list) {
 | |
|                print "   $compat\n";
 | |
|        }
 | |
| 
 | |
| 
 | |
|        print "\n\n";
 | |
|        print "The driver for these compatibles is hard coded (white list).\n";
 | |
|        print "\n";
 | |
|        my $max_compat_len = 0;
 | |
|        for my $compat (sort keys %driver_hard_code_list) {
 | |
|                if (length $compat > $max_compat_len) {
 | |
|                        $max_compat_len = length $compat;
 | |
|                }
 | |
|        }
 | |
|        for my $compat (sort keys %driver_hard_code_list) {
 | |
|                if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
 | |
|                        my $first = 1;
 | |
|                        for my $driver (@{ $driver_hard_code_list{$compat} }) {
 | |
|                                if ($first) {
 | |
|                                        print "   $compat";
 | |
|                                        print " " x ($max_compat_len - length $compat);
 | |
|                                        $first = 0;
 | |
|                                } else {
 | |
|                                        print "   ", " " x $max_compat_len;
 | |
|                                }
 | |
|                                print "  $driver\n";
 | |
|                        }
 | |
|                }
 | |
|        }
 | |
| 
 | |
| 
 | |
|        print "\n\n";
 | |
|        print "The configuration option for these drivers is hard coded (white list).\n";
 | |
|        print "\n";
 | |
|        my $max_driver_len = 0;
 | |
|        for my $driver (sort keys %driver_config_hard_code_list) {
 | |
|                if (length $driver > $max_driver_len) {
 | |
|                        $max_driver_len = length $driver;
 | |
|                }
 | |
|        }
 | |
|        for my $driver (sort keys %driver_config_hard_code_list) {
 | |
|                if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
 | |
|                        my $first = 1;
 | |
|                        for my $config (@{ $driver_config_hard_code_list{$driver} }) {
 | |
|                                if ($first) {
 | |
|                                        print "   $driver";
 | |
|                                        print " " x ($max_driver_len - length $driver);
 | |
|                                        $first = 0;
 | |
|                                } else {
 | |
|                                        print "   ", " " x $max_driver_len;
 | |
|                                }
 | |
|                                print "  $config\n";
 | |
|                        }
 | |
|                }
 | |
|        }
 | |
| 
 | |
| 
 | |
|        print "\n\n";
 | |
|        print "These drivers are black listed.\n";
 | |
|        print "\n";
 | |
|        for my $driver (@black_list_driver) {
 | |
|                print "   $driver\n";
 | |
|        }
 | |
| 
 | |
|        print "\n";
 | |
| 
 | |
|        $exit_after_messages = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| if ($exit_after_messages) {
 | |
|        exit 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| $exclude_flag_pattern = "[";
 | |
| for my $exclude_flag (@exclude_flag) {
 | |
|        $exclude_flag_pattern = $exclude_flag_pattern . $exclude_flag;
 | |
| }
 | |
| $exclude_flag_pattern = $exclude_flag_pattern . "]";
 | |
| # clean up if empty
 | |
| $exclude_flag_pattern =~ s/^\[\]$//;
 | |
| 
 | |
| 
 | |
| $include_flag_pattern = "[";
 | |
| for my $include_flag (@include_flag) {
 | |
|        $include_flag_pattern = $include_flag_pattern . $include_flag;
 | |
| }
 | |
| $include_flag_pattern = $include_flag_pattern . "]";
 | |
| # clean up if empty
 | |
| $include_flag_pattern =~ s/^\[\]$//;
 | |
| 
 | |
| 
 | |
| if ($exclude_flag_pattern) {
 | |
|        my $found = 0;
 | |
|        for $pr_flag_value (@pr_flag_value) {
 | |
|                if ($exclude_flag_pattern =~ m/$pr_flag_value/) {
 | |
|                        $found = 1;
 | |
|                }
 | |
|        }
 | |
|        if (!$found) {
 | |
|                &cmd_line_err("invalid value for FLAG in --exclude-flag\n");
 | |
|                exit 1
 | |
|        }
 | |
| }
 | |
| 
 | |
| if ($include_flag_pattern) {
 | |
|        my $found = 0;
 | |
|        for $pr_flag_value (@pr_flag_value) {
 | |
|                if ($include_flag_pattern =~ m/$pr_flag_value/) {
 | |
|                        $found = 1;
 | |
|                }
 | |
|        }
 | |
|        if (!$found) {
 | |
|                &cmd_line_err("invalid value for FLAG in --include-flag\n");
 | |
|                exit 1
 | |
|        }
 | |
| }
 | |
| 
 | |
| if ($include_suspect) {
 | |
|        $include_flag_pattern =~ s/\[//;
 | |
|        $include_flag_pattern =~ s/\]//;
 | |
|        $include_flag_pattern = "[" . $include_flag_pattern . "A-Z]";
 | |
| }
 | |
| 
 | |
| if ($exclude_flag_pattern =~ m/$include_flag_pattern/) {
 | |
|        &cmd_line_err("the same flag appears in both --exclude-flag and --include-flag or --include-suspect\n");
 | |
|        exit 1
 | |
| }
 | |
| 
 | |
| 
 | |
| # ($#ARGV < 0) is valid for --help, --version
 | |
| if ($#ARGV < 0) {
 | |
|        &cmd_line_err("device-tree... is required");
 | |
|        exit 1
 | |
| }
 | |
| 
 | |
| 
 | |
| if ($config_file) {
 | |
|        &read_config_file();
 | |
| }
 | |
| 
 | |
| 
 | |
| # avoid pushing duplicates for this value
 | |
| $driver = "hardcoded_no_driver";
 | |
| for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
 | |
|        push @{ $driver_config{$driver} }, $config;
 | |
| }
 | |
| 
 | |
| if ($white_list_driver) {
 | |
|        for my $compat (keys %driver_hard_code_list) {
 | |
|                for my $driver (@{ $driver_hard_code_list{$compat} }) {
 | |
|                        push @{ $compat_driver{$compat} }, $driver;
 | |
|                        if ($driver ne "hardcoded_no_driver") {
 | |
|                                $driver_count{$compat} = scalar @{ $compat_driver{$compat} };
 | |
|                        }
 | |
|                }
 | |
|        }
 | |
| }
 | |
| 
 | |
| if ($white_list_config) {
 | |
|        for my $driver (keys %driver_config_hard_code_list) {
 | |
|                if ($driver ne "hardcoded_no_driver") {
 | |
|                        for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
 | |
|                                push @{ $driver_config{$driver} }, $config;
 | |
|                        }
 | |
|                }
 | |
|        }
 | |
| }
 | |
| 
 | |
| if (-x "scripts/dtc/dtx_diff") {
 | |
|        $dtx_diff = "scripts/dtc/dtx_diff";
 | |
| } else {
 | |
| 
 | |
|        print STDERR "\n";
 | |
|        print STDERR "$script_name must be run from the root directory of a Linux kernel tree\n";
 | |
|        print STDERR "\n";
 | |
|        exit 3;
 | |
| }
 | |
| 
 | |
| for $file (@ARGV) {
 | |
|        &read_dts($file);
 | |
| }
 |