~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/dtc/dt_to_config

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/usr/bin/env perl
  2 # SPDX-License-Identifier: GPL-2.0-only
  3 
  4 # Copyright 2016 by Frank Rowand
  5 # Copyright 2016 by Gaurav Minocha
  6 #
  7 
  8 use strict 'refs';
  9 use strict subs;
 10 
 11 use Getopt::Long;
 12 
 13 $VUFX = "160610a";
 14 
 15 $script_name = $0;
 16 $script_name =~ s|^.*/||;
 17 
 18 
 19 # ----- constants for print_flags()
 20 
 21 # Position in string $pr_flags.  Range of 0..($num_pr_flags - 1).
 22 $pr_flag_pos_mcompatible       = 0;
 23 $pr_flag_pos_driver            = 1;
 24 $pr_flag_pos_mdriver           = 2;
 25 $pr_flag_pos_config            = 3;
 26 $pr_flag_pos_mconfig           = 4;
 27 $pr_flag_pos_node_not_enabled  = 5;
 28 $pr_flag_pos_white_list        = 6;
 29 $pr_flag_pos_hard_coded        = 7;
 30 $pr_flag_pos_config_hard_coded = 8;
 31 $pr_flag_pos_config_none       = 9;
 32 $pr_flag_pos_config_m          = 10;
 33 $pr_flag_pos_config_y          = 11;
 34 $pr_flag_pos_config_test_fail  = 12;
 35 
 36 $num_pr_flags = $pr_flag_pos_config_test_fail + 1;
 37 
 38 # flags in @pr_flag_value must be unique values to allow simple regular
 39 # expessions to work for --include_flags and --exclude_flags.
 40 # Convention: use upper case letters for potential issues or problems.
 41 
 42 @pr_flag_value = ('M', 'd', 'D', 'c', 'C', 'E', 'W', 'H', 'x', 'n', 'm', 'y', 'F');
 43 
 44 @pr_flag_help = (
 45     "multiple compatibles found for this node",
 46     "driver found for this compatible",
 47     "multiple drivers found for this compatible",
 48     "kernel config found for this driver",
 49     "multiple config options found for this driver",
 50     "node is not enabled",
 51     "compatible is white listed",
 52     "matching driver and/or kernel config is hard coded",
 53     "kernel config hard coded in Makefile",
 54     "one or more kernel config file options is not set",
 55     "one or more kernel config file options is set to 'm'",
 56     "one or more kernel config file options is set to 'y'",
 57     "one of more kernel config file options fails to have correct value"
 58 );
 59 
 60 
 61 # -----
 62 
 63 %driver_config = ();   # driver config array, indexed by driver source file
 64 %driver_count = ();    # driver_cnt, indexed by compatible
 65 %compat_driver = ();   # compatible driver array, indexed by compatible
 66 %existing_config = (); # existing config symbols present in given config file
 67                        # expected values are: "y", "m", a decimal number, a
 68                        # hex number, or a string
 69 
 70 # ----- magic compatibles, do not have a driver
 71 #
 72 # Will not search for drivers for these compatibles.
 73 
 74 %compat_white_list = (
 75        'none'                  => '1',
 76        'pci'                   => '1',
 77        'simple-bus'            => '1',
 78 );
 79 
 80 # Will not search for drivers for these compatibles.
 81 #
 82 # These compatibles have a very large number of false positives.
 83 #
 84 # 'hardcoded_no_driver' is a magic value.  Other code knows this
 85 # magic value.  Do not use 'no_driver' here!
 86 #
 87 # Revisit each 'hardcoded_no_driver' to see how the compatible
 88 # is used.  Are there drivers that can be provided?
 89 
 90 %driver_hard_code_list = (
 91        'cache'                 => ['hardcoded_no_driver'],
 92        'eeprom'                => ['hardcoded_no_driver'],
 93        'gpio'                  => ['hardcoded_no_driver'],
 94        'gpio-keys'             => ['drivers/input/keyboard/gpio_keys.c'],
 95        'i2c-gpio'              => ['drivers/i2c/busses/i2c-gpio.c'],
 96        'isa'                   => ['arch/mips/mti-malta/malta-dt.c',
 97                                     'arch/x86/kernel/devicetree.c'],
 98        'led'                   => ['hardcoded_no_driver'],
 99        'm25p32'                => ['hardcoded_no_driver'],
100        'm25p64'                => ['hardcoded_no_driver'],
101        'm25p80'                => ['hardcoded_no_driver'],
102        'mtd-ram'               => ['drivers/mtd/maps/physmap_of.c'],
103        'pwm-backlight'         => ['drivers/video/backlight/pwm_bl.c'],
104        'spidev'                => ['hardcoded_no_driver'],
105        'syscon'                => ['drivers/mfd/syscon.c'],
106        'tlv320aic23'           => ['hardcoded_no_driver'],
107        'wm8731'                => ['hardcoded_no_driver'],
108 );
109 
110 # Use these config options instead of searching makefiles
111 
112 %driver_config_hard_code_list = (
113 
114        # this one needed even if %driver_hard_code_list is empty
115        'no_driver'                             => ['no_config'],
116        'hardcoded_no_driver'                   => ['no_config'],
117 
118        # drivers/usb/host/ehci-ppc-of.c
119        # drivers/usb/host/ehci-xilinx-of.c
120        #  are included from:
121        #    drivers/usb/host/ehci-hcd.c
122        #  thus the search of Makefile for the included .c files is incorrect
123        # ehci-hcd.c wraps the includes with ifdef CONFIG_USB_EHCI_HCD_..._OF
124        #
125        # similar model for ohci-hcd.c (but no ohci-xilinx-of.c)
126        #
127        # similarly, uhci-hcd.c includes uhci-platform.c
128 
129        'drivers/usb/host/ehci-ppc-of.c'        => ['CONFIG_USB_EHCI_HCD',
130                                                    'CONFIG_USB_EHCI_HCD_PPC_OF'],
131        'drivers/usb/host/ohci-ppc-of.c'        => ['CONFIG_USB_OHCI_HCD',
132                                                    'CONFIG_USB_OHCI_HCD_PPC_OF'],
133 
134        'drivers/usb/host/ehci-xilinx-of.c'     => ['CONFIG_USB_EHCI_HCD',
135                                                    'CONFIG_USB_EHCI_HCD_XILINX'],
136 
137        'drivers/usb/host/uhci-platform.c'      => ['CONFIG_USB_UHCI_HCD',
138                                                    'CONFIG_USB_UHCI_PLATFORM'],
139 
140        # scan_makefile will find only one of these config options:
141        #    ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
142        'arch/arm/mach-imx/platsmp.c'           => ['CONFIG_SOC_IMX6 && CONFIG_SMP',
143                                                    'CONFIG_SOC_LS1021A && CONFIG_SMP'],
144 );
145 
146 
147 # 'virt/kvm/arm/.*' are controlled by makefiles in other directories,
148 # using relative paths, such as 'KVM := ../../../virt/kvm'.  Do not
149 # add complexity to find_kconfig() to deal with this.  There is a long
150 # term intent to change the kvm related makefiles to the normal kernel
151 # style.  After that is done, this entry can be removed from the
152 # black_list_driver.
153 
154 @black_list_driver = (
155        # kvm no longer a problem after commit 503a62862e8f in 4.7-rc1
156        # 'virt/kvm/arm/.*',
157 );
158 
159 
160 sub usage()
161 {
162        print
163 "
164 Usage: $script_name [options] device-tree...
165 
166     device_tree is: dts_file | dtb_file | proc_device-tree
167 
168 
169 Valid options:
170      -c FILE             Read kernel config options from FILE
171     --config FILE        synonym for 'c'
172     --config-format      config file friendly output format
173     --exclude-flag FLAG  exclude entries with a matching flag
174      -h                  Display this message and exit
175     --help               synonym for 'h'
176     --black-list-driver  use driver black list
177     --white-list-config  use config white list
178     --white-list-driver  use driver white list
179     --include-flag FLAG  include only entries with a matching flag
180     --include-suspect    include only entries with an uppercase flag
181     --short-name         do not show the path portion of the node name
182     --show-lists         report of white and black lists
183     --version            Display program version and exit
184 
185 
186   Report driver source files that match the compatibles in the device
187   tree file and the kernel config options that enable the driver source
188   files.
189 
190   This program must be run in the root directory of a Linux kernel
191   source tree.
192 
193   The default format is a report that is intended to be easily human
194   scannable.
195 
196   An alternate format can be selected by --config-format.  This will
197   create output that can easily be edited to create a fragment that can
198   be appended to the existing kernel config file.  Each entry consists of
199   multiple lines.  The first line reports flags, the node path, compatible
200   value, driver file matching the compatible, configuration options, and
201   current values of the configuration options.  For each configuration
202   option, the following lines report the current value and the value that
203   is required for the driver file to be included in the kernel.
204 
205   If a large number of drivers or config options is listed for a node,
206   and the '$pr_flag_value[$pr_flag_pos_hard_coded]' flag is set consider using --white-list-config and/or
207   --white-list-driver.  If the white list option suppresses the correct
208   entry please report that as a bug.
209 
210   CAUTION:
211      This program uses heuristics to guess which driver(s) support each
212      compatible string and which config option(s) enables the driver(s).
213      Do not believe that the reported information is fully correct.
214      This program is intended to aid the process of determining the
215      proper kernel configuration for a device tree, but this is not
216      a fully automated process -- human involvement may still be
217      required!
218 
219      The driver match heuristic used is to search for source files
220      containing the compatible string enclosed in quotes.
221 
222      This program might not be able to find all drivers matching a
223      compatible string.
224 
225      Some makefiles are overly clever.  This program was not made
226      complex enough to handle them.  If no config option is listed
227      for a driver, look at the makefile for the driver source file.
228      Even if a config option is listed for a driver, some other
229      available config options may not be listed.
230 
231   FLAG values:
232 ";
233 
234        for ($k = 0; $k < $num_pr_flags; $k++) {
235                printf "     %s   %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
236        }
237 
238        print
239 "
240      Upper case letters indicate potential issues or problems.
241 
242   The flag:
243 
244 ";
245 
246        $k = $pr_flag_pos_hard_coded;
247        printf "     %s   %s\n", $pr_flag_value[$k], $pr_flag_help[$k];
248 
249        print
250 "
251   will be set if the config or driver is in the white lists, even if
252   --white-list-config and --white-list-driver are not specified.
253   This is a hint that 1) many of these reported lines are likely to
254   be incorrect, and 2) using those options will reduce the number of
255   drivers and/or config options reported.
256 
257   --white-list-config and --white-list-driver may not be accurate if this
258   program is not well maintained.  Use them with appropriate skepticism.
259   Use the --show-lists option to report the values in the list.
260 
261   Return value:
262     0   if no error
263     1   error processing command line
264     2   unable to open or read kernel config file
265     3   unable to open or process input device tree file(s)
266 
267   EXAMPLES:
268 
269      dt_to_config arch/arm/boot/dts/my_dts_file.dts
270 
271        Basic report.
272 
273      dt_to_config \\
274         --config \${KBUILD_OUTPUT}/.config \\
275         arch/\${ARCH}/boot/dts/my_dts_file.dts
276 
277        Full report, with config file issues noted.
278 
279      dt_to_config --include-suspect \\
280         --config \${KBUILD_OUTPUT}/.config \\
281         arch/\${ARCH}/boot/dts/my_dts_file.dts
282 
283        Report of node / compatible string / driver tuples that should
284        be further investigated.  A node may have multiple compatible
285        strings.  A compatible string may be matched by multiple drivers.
286        A driver may have config file issues noted.  The compatible string
287        and/or driver may be in the white lists.
288 
289      dt_to_config --include-suspect --config-format \\
290         --config ${KBUILD_OUTPUT}/.config \\
291         arch/\${ARCH}/boot/dts/my_dts_file.dts
292 
293        Report of node / compatible string / driver tuples that should
294        be further investigated.  The report can be edited to uncomment
295        the config options to select the desired tuple for a given node.
296        A node may have multiple compatible strings.  A compatible string
297        may be matched by multiple drivers.  A driver may have config file
298        issues noted.  The compatible string and/or driver may be in the
299        white lists.
300 
301 ";
302 }
303 
304 sub set_flag()
305 {
306        # pr_flags_ref is a reference to $pr_flags
307 
308        my $pr_flags_ref = shift;
309        my $pos          = shift;
310 
311        substr $$pr_flags_ref, $pos, 1, $pr_flag_value[$pos];
312 
313        return $pr_flags;
314 }
315 
316 sub print_flags()
317 {
318        # return 1 if anything printed, else 0
319 
320        # some fields of pn_arg_ref might not be used in this function, but
321        # extract all of them anyway.
322        my $pn_arg_ref     = shift;
323 
324        my $compat         = $pn_arg_ref->{compat};
325        my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
326        my $config         = $pn_arg_ref->{config};
327        my $config_cnt     = $pn_arg_ref->{config_cnt};
328        my $driver         = $pn_arg_ref->{driver};
329        my $driver_cnt     = $pn_arg_ref->{driver_cnt};
330        my $full_node      = $pn_arg_ref->{full_node};
331        my $node           = $pn_arg_ref->{node};
332        my $node_enabled   = $pn_arg_ref->{node_enabled};
333        my $white_list     = $pn_arg_ref->{white_list};
334 
335        my $pr_flags       = '-' x $num_pr_flags;
336 
337 
338        # ----- set flags in $pr_flags
339 
340        if ($compatible_cnt > 1) {
341                &set_flag(\$pr_flags, $pr_flag_pos_mcompatible);
342        }
343 
344        if ($config_cnt > 1) {
345                &set_flag(\$pr_flags, $pr_flag_pos_mconfig);
346        }
347 
348        if ($driver_cnt >= 1) {
349                &set_flag(\$pr_flags, $pr_flag_pos_driver);
350        }
351 
352        if ($driver_cnt > 1) {
353                &set_flag(\$pr_flags, $pr_flag_pos_mdriver);
354        }
355 
356        # These strings are the same way the linux kernel tests.
357        # The ePapr lists of values is slightly different.
358        if (!(
359              ($node_enabled eq "") ||
360              ($node_enabled eq "ok") ||
361              ($node_enabled eq "okay")
362             )) {
363                &set_flag(\$pr_flags, $pr_flag_pos_node_not_enabled);
364        }
365 
366        if ($white_list) {
367                &set_flag(\$pr_flags, $pr_flag_pos_white_list);
368        }
369 
370        if (exists($driver_hard_code_list{$compat}) ||
371            (exists($driver_config_hard_code_list{$driver}) &&
372             ($driver ne "no_driver"))) {
373                &set_flag(\$pr_flags, $pr_flag_pos_hard_coded);
374        }
375 
376        my @configs = split(' && ', $config);
377        for $configs (@configs) {
378                $not = $configs =~ /^!/;
379                $configs =~ s/^!//;
380 
381                if (($configs ne "no_config") && ($configs ne "no_makefile")) {
382                        &set_flag(\$pr_flags, $pr_flag_pos_config);
383                }
384 
385                if (($config_cnt >= 1) &&
386                    ($configs !~ /CONFIG_/) &&
387                    (($configs ne "no_config") && ($configs ne "no_makefile"))) {
388                        &set_flag(\$pr_flags, $pr_flag_pos_config_hard_coded);
389                }
390 
391                my $existing_config = $existing_config{$configs};
392                if ($existing_config eq "m") {
393                        &set_flag(\$pr_flags, $pr_flag_pos_config_m);
394                        # Possible fail, depends on whether built in or
395                        # module is desired.
396                        &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
397                } elsif ($existing_config eq "y") {
398                        &set_flag(\$pr_flags, $pr_flag_pos_config_y);
399                        if ($not) {
400                                &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
401                        }
402                } elsif (($config_file) && ($configs =~ /CONFIG_/)) {
403                        &set_flag(\$pr_flags, $pr_flag_pos_config_none);
404                        if (!$not) {
405                                &set_flag(\$pr_flags, $pr_flag_pos_config_test_fail);
406                        }
407                }
408        }
409 
410        # ----- include / exclude filters
411 
412        if ($include_flag_pattern && ($pr_flags !~ m/$include_flag_pattern/)) {
413                return 0;
414        }
415 
416        if ($exclude_flag_pattern && ($pr_flags =~ m/$exclude_flag_pattern/)) {
417                return 0;
418        }
419 
420        if ($config_format) {
421                print "# ";
422        }
423        print "$pr_flags : ";
424 
425        return 1;
426 }
427 
428 
429 sub print_node()
430 {
431        # return number of lines printed
432 
433        # some fields of pn_arg_ref might not be used in this function, but
434        # extract all of them anyway.
435        my $pn_arg_ref     = shift;
436 
437        my $compat         = $pn_arg_ref->{compat};
438        my $compatible_cnt = $pn_arg_ref->{compatible_cnt};
439        my $config         = $pn_arg_ref->{config};
440        my $config_cnt     = $pn_arg_ref->{config_cnt};
441        my $driver         = $pn_arg_ref->{driver};
442        my $driver_cnt     = $pn_arg_ref->{driver_cnt};
443        my $full_node      = $pn_arg_ref->{full_node};
444        my $node           = $pn_arg_ref->{node};
445        my $node_enabled   = $pn_arg_ref->{node_enabled};
446        my $white_list     = $pn_arg_ref->{white_list};
447 
448        my $separator;
449 
450        if (! &print_flags($pn_arg_ref)) {
451                return 0;
452        }
453 
454 
455        if ($short_name) {
456                print "$node";
457        } else {
458                print "$full_node";
459        }
460        print " : $compat : $driver : $config : ";
461 
462        my @configs = split(' && ', $config);
463 
464        if ($config_file) {
465                for $configs (@configs) {
466                        $configs =~ s/^!//;
467                        my $existing_config = $existing_config{$configs};
468                        if (!$existing_config) {
469                                # check for /-m/, /-y/, or /-objs/
470                                if ($configs !~ /CONFIG_/) {
471                                        $existing_config = "x";
472                                };
473                        };
474                        if ($existing_config) {
475                                print "$separator", "$existing_config";
476                                $separator = ", ";
477                        } else {
478                                print "$separator", "n";
479                                $separator = ", ";
480                        }
481                }
482        } else {
483                print "none";
484        }
485 
486        print "\n";
487 
488        if ($config_format) {
489                for $configs (@configs) {
490                        $not = $configs =~ /^!/;
491                        $configs =~ s/^!//;
492                        my $existing_config = $existing_config{$configs};
493 
494                        if ($not) {
495                                if ($configs !~ /CONFIG_/) {
496                                        print "# $configs\n";
497                                } elsif ($existing_config eq "m") {
498                                        print "# $configs is m\n";
499                                        print "# $configs=n\n";
500                                } elsif ($existing_config eq "y") {
501                                        print "# $configs is set\n";
502                                        print "# $configs=n\n";
503                                } else {
504                                        print "# $configs is not set\n";
505                                        print "# $configs=n\n";
506                                }
507 
508                        } else {
509                                if ($configs !~ /CONFIG_/) {
510                                        print "# $configs\n";
511                                } elsif ($existing_config eq "m") {
512                                        print "# $configs is m\n";
513                                        print "# $configs=y\n";
514                                } elsif ($existing_config eq "y") {
515                                        print "# $configs is set\n";
516                                        print "# $configs=y\n";
517                                } else {
518                                        print "# $configs is not set\n";
519                                        print "# $configs=y\n";
520                                }
521                        }
522                }
523        }
524 
525        return 1;
526 }
527 
528 
529 sub scan_makefile
530 {
531        my $pn_arg_ref    = shift;
532        my $driver        = shift;
533 
534        # ----- Find Kconfig symbols that enable driver
535 
536        my ($dir, $base) = $driver =~ m{(.*)/(.*).c};
537 
538        my $makefile = $dir . "/Makefile";
539        if (! -r $makefile) {
540                $makefile = $dir . "/Kbuild";
541        }
542        if (! -r $makefile) {
543                my $config;
544 
545                $config = 'no_makefile';
546                push @{ $driver_config{$driver} }, $config;
547                return;
548        }
549 
550        if (!open(MAKEFILE_FILE, "<", "$makefile")) {
551                return;
552        }
553 
554        my $line;
555        my @config;
556        my @if_config;
557        my @make_var;
558 
559        NEXT_LINE:
560        while ($next_line = <MAKEFILE_FILE>) {
561                my $config;
562                my $if_config;
563                my $ifdef;
564                my $ifeq;
565                my $ifndef;
566                my $ifneq;
567                my $ifdef_config;
568                my $ifeq_config;
569                my $ifndef_config;
570                my $ifneq_config;
571 
572                chomp($next_line);
573                $line = $line . $next_line;
574                if ($next_line =~ /\\$/) {
575                        $line =~ s/\\$/ /;
576                        next NEXT_LINE;
577                }
578                if ($line =~ /^\s*#/) {
579                        $line = "";
580                        next NEXT_LINE;
581                }
582 
583                # -----  condition ... else ... endif
584 
585                if ($line =~ /^([ ]\s*|)else\b/) {
586                        $if_config = "!" . pop @if_config;
587                        $if_config =~ s/^!!//;
588                        push @if_config, $if_config;
589                        $line =~ s/^([ ]\s*|)else\b//;
590                }
591 
592                ($null, $ifeq_config,  $ifeq_config_val )  = $line =~ /^([ ]\s*|)ifeq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
593                ($null, $ifneq_config, $ifneq_config_val)  = $line =~ /^([ ]\s*|)ifneq\b.*\b(CONFIG_[A-Za-z0-9_]*)(.*)/;
594                ($null, $ifdef_config)                     = $line =~ /^([ ]\s*|)ifdef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
595                ($null, $ifndef_config)                    = $line =~ /^([ ]\s*|)ifndef\b.*\b(CONFIG_[A-Za-z0-9_]*)/;
596 
597                ($null, $ifeq)   = $line =~ /^([ ]\s*|)ifeq\b\s*(.*)/;
598                ($null, $ifneq)  = $line =~ /^([ ]\s*|)ifneq\b\s*(.*)/;
599                ($null, $ifdef)  = $line =~ /^([ ]\s*|)ifdef\b\s*(.*)/;
600                ($null, $ifndef) = $line =~ /^([ ]\s*|)ifndef\b\s*(.*)/;
601 
602                # Order of tests is important.  Prefer "CONFIG_*" regex match over
603                # less specific regex match.
604                if ($ifdef_config) {
605                        $if_config = $ifdef_config;
606                } elsif ($ifeq_config) {
607                        if ($ifeq_config_val =~ /y/) {
608                                $if_config = $ifeq_config;
609                        } else {
610                                $if_config = "!" . $ifeq_config;
611                        }
612                } elsif ($ifndef_config) {
613                        $if_config = "!" . $ifndef_config;
614                } elsif ($ifneq_config) {
615                        if ($ifneq_config_val =~ /y/) {
616                                $if_config = "!" . $ifneq_config;
617                        } else {
618                                $if_config = $ifneq_config;
619                        }
620                } elsif ($ifdef) {
621                        $if_config = $ifdef;
622                } elsif ($ifeq) {
623                        $if_config = $ifeq;
624                } elsif ($ifndef) {
625                        $if_config = "!" . $ifndef;
626                } elsif ($ifneq) {
627                        $if_config = "!" . $ifneq;
628                } else {
629                        $if_config = "";
630                }
631                $if_config =~ s/^!!//;
632 
633                if ($if_config) {
634                        push @if_config, $if_config;
635                        $line = "";
636                        next NEXT_LINE;
637                }
638 
639                if ($line =~ /^([ ]\s*|)endif\b/) {
640                        pop @if_config;
641                        $line = "";
642                        next NEXT_LINE;
643                }
644 
645                # ----- simple CONFIG_* = *.[co]  or  xxx [+:?]*= *.[co]
646                # Most makefiles select on *.o, but
647                # arch/powerpc/boot/Makefile selects on *.c
648 
649                ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$base.[co]\b/;
650 
651                # ----- match a make variable instead of *.[co]
652                # Recursively expanded variables are not handled.
653 
654                if (!$config) {
655                        my $make_var;
656                        ($make_var) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$base.[co]\b/;
657                        if ($make_var) {
658                                if ($make_var =~ /[a-zA-Z0-9]+-[ym]/) {
659                                        $config = $make_var;
660                                } elsif ($make_var =~ /[a-zA-Z0-9]+-objs/) {
661                                        $config = $make_var;
662                                } else {
663                                        push @make_var, $make_var;
664                                }
665                        }
666                }
667 
668                if (!$config) {
669                        for $make_var (@make_var) {
670                                ($config) = $line =~ /(CONFIG_[A-Za-z0-9_]+).*\b$make_var\b/;
671                                last if ($config);
672                        }
673                }
674 
675                if (!$config) {
676                        for $make_var (@make_var) {
677                                ($config) = $line =~ /\s*(\S+?)\s*[+:\?]*=.*\b$make_var\b/;
678                                last if ($config);
679                        }
680                }
681 
682                # ----- next if no config found
683 
684                if (!$config) {
685                        $line = "";
686                        next NEXT_LINE;
687                }
688 
689                for $if_config (@if_config) {
690                        $config = $if_config . " && " . $config;
691                }
692 
693                push @{ $driver_config{$driver} }, $config;
694 
695                $line = "";
696        }
697 
698        close(MAKEFILE_FILE);
699 
700 }
701 
702 
703 sub find_kconfig
704 {
705        my $pn_arg_ref    = shift;
706        my $driver        = shift;
707 
708        my $lines_printed = 0;
709        my @configs;
710 
711        if (!@{ $driver_config{$driver} }) {
712                &scan_makefile($pn_arg_ref, $driver);
713                if (!@{ $driver_config{$driver} }) {
714                        push @{ $driver_config{$driver} }, "no_config";
715                }
716        }
717 
718        @configs = @{ $driver_config{$driver} };
719 
720        $$pn_arg_ref{config_cnt} = $#configs + 1;
721        for my $config (@configs) {
722                $$pn_arg_ref{config} = $config;
723                $lines_printed += &print_node($pn_arg_ref);
724        }
725 
726        return $lines_printed;
727 }
728 
729 
730 sub handle_compatible()
731 {
732        my $full_node     = shift;
733        my $node          = shift;
734        my $compatible    = shift;
735        my $node_enabled  = shift;
736 
737        my $compat;
738        my $lines_printed = 0;
739        my %pn_arg        = ();
740 
741        return if (!$node or !$compatible);
742 
743        # Do not process compatible property of root node,
744        # it is used to match board, not to bind a driver.
745        return if ($node eq "/");
746 
747        $pn_arg{full_node}    = $full_node;
748        $pn_arg{node}         = $node;
749        $pn_arg{node_enabled} = $node_enabled;
750 
751        my @compatibles = split('", "', $compatible);
752 
753        $compatibles[0] =~ s/^"//;
754        $compatibles[$#compatibles] =~ s/"$//;
755 
756        $pn_arg{compatible_cnt} = $#compatibles + 1;
757 
758        COMPAT:
759        for $compat (@compatibles) {
760 
761                $pn_arg{compat}     = $compat;
762                $pn_arg{driver_cnt} = 0;
763                $pn_arg{white_list} = 0;
764 
765                if (exists($compat_white_list{$compat})) {
766                        $pn_arg{white_list} = 1;
767                        $pn_arg{driver}     = "no_driver";
768                        $pn_arg{config_cnt} = 1;
769                        $pn_arg{config}     = "no_config";
770                        $lines_printed += &print_node(\%pn_arg);
771                        next COMPAT;
772                }
773 
774                # ----- if compat previously seen, use cached info
775 
776                if (exists($compat_driver{$compat})) {
777                        for my $driver (@{ $compat_driver{$compat} }) {
778                                $pn_arg{driver}     = $driver;
779                                $pn_arg{driver_cnt} = $driver_count{$compat};
780                                $pn_arg{config_cnt} = $#{ $driver_config{$driver}} + 1;
781 
782                                for my $config (@{ $driver_config{$driver} }) {
783                                        $pn_arg{config} = $config;
784                                        $lines_printed += &print_node(\%pn_arg);
785                                }
786 
787                                if (!@{ $driver_config{$driver} }) {
788                                        # no config cached yet
789                                        # $driver in %driver_hard_code_list
790                                        # but not %driver_config_hard_code_list
791                                        $lines_printed += &find_kconfig(\%pn_arg, $driver);
792                                }
793                        }
794                        next COMPAT;
795                }
796 
797 
798                # ----- Find drivers (source files that contain compatible)
799 
800                # this will miss arch/sparc/include/asm/parport.h
801                # It is better to move the compatible out of the .h
802                # than to add *.h. to the files list, because *.h generates
803                # a lot of false negatives.
804                my $files = '"*.c"';
805                my $drivers = `git grep -l '"$compat"' -- $files`;
806                chomp($drivers);
807                if ($drivers eq "") {
808                        $pn_arg{driver} = "no_driver";
809                        $pn_arg{config_cnt} = 1;
810                        $pn_arg{config} = "no_config";
811                        push @{ $compat_driver{$compat} }, "no_driver";
812                        $lines_printed += &print_node(\%pn_arg);
813                        next COMPAT;
814                }
815 
816                my @drivers = split("\n", $drivers);
817                $driver_count{$compat} = $#drivers + 1;
818                $pn_arg{driver_cnt}    = $#drivers + 1;
819 
820                DRIVER:
821                for my $driver (@drivers) {
822                        push @{ $compat_driver{$compat} }, $driver;
823                        $pn_arg{driver} = $driver;
824 
825                        # ----- if driver previously seen, use cached info
826 
827                        $pn_arg{config_cnt} = $#{ $driver_config{$driver} } + 1;
828                        for my $config (@{ $driver_config{$driver} }) {
829                                $pn_arg{config} = $config;
830                                $lines_printed += &print_node(\%pn_arg);
831                        }
832                        if (@{ $driver_config{$driver} }) {
833                                next DRIVER;
834                        }
835 
836                        if ($black_list_driver) {
837                                for $black (@black_list_driver) {
838                                        next DRIVER if ($driver =~ /^$black$/);
839                                }
840                        }
841 
842 
843                        # ----- Find Kconfig symbols that enable driver
844 
845                        $lines_printed += &find_kconfig(\%pn_arg, $driver);
846 
847                }
848        }
849 
850        # White space (line) between nodes for readability.
851        # Each node may report several compatibles.
852        # For each compatible, multiple drivers may be reported.
853        # For each driver, multiple CONFIG_ options may be reported.
854        if ($lines_printed) {
855                print "\n";
856        }
857 }
858 
859 sub read_dts()
860 {
861        my $file         = shift;
862 
863        my $compatible   = "";
864        my $line;
865        my $node         = "";
866        my $node_enabled = "";
867 
868        if (! -r $file) {
869                print STDERR "file '$file' is not readable or does not exist\n";
870                exit 3;
871        }
872 
873        if (!open(DT_FILE, "-|", "$dtx_diff $file")) {
874                print STDERR "\n";
875                print STDERR "shell command failed:\n";
876                print STDERR "   $dtx_diff $file\n";
877                print STDERR "\n";
878                exit 3;
879        }
880 
881        FILE:
882        while ($line = <DT_FILE>) {
883                chomp($line);
884 
885                if ($line =~ /{/) {
886 
887                        &handle_compatible($full_node, $node, $compatible,
888                                           $node_enabled);
889 
890                        while ($end_node_count-- > 0) {
891                                pop @full_node;
892                        };
893                        $end_node_count = 0;
894                        $full_node = @full_node[-1];
895 
896                        $node = $line;
897                        $node =~ s/^\s*(.*)\s+\{.*/$1/;
898                        $node =~ s/.*: //;
899                        if ($node eq '/' ) {
900                                $full_node = '/';
901                        } elsif ($full_node ne '/') {
902                                $full_node = $full_node . '/' . $node;
903                        } else {
904                                $full_node = '/' . $node;
905                        }
906                        push @full_node, $full_node;
907 
908                        $compatible = "";
909                        $node_enabled = "";
910                        next FILE;
911                }
912 
913                if ($line =~ /}/) {
914                        $end_node_count++;
915                }
916 
917                if ($line =~ /(\s+|^)status =/) {
918                        $node_enabled = $line;
919                        $node_enabled =~ s/^\t*//;
920                        $node_enabled =~ s/^status = "//;
921                        $node_enabled =~ s/";$//;
922                        next FILE;
923                }
924 
925                if ($line =~ /(\s+|^)compatible =/) {
926                        # Extract all compatible entries for this device
927                        # White space matching here and in handle_compatible() is
928                        # precise, because input format is the output of dtc,
929                        # which is invoked by dtx_diff.
930                        $compatible = $line;
931                        $compatible =~ s/^\t*//;
932                        $compatible =~ s/^compatible = //;
933                        $compatible =~ s/;$//;
934                }
935        }
936 
937        &handle_compatible($full_node, $node, $compatible, $node_enabled);
938 
939        close(DT_FILE);
940 }
941 
942 
943 sub read_config_file()
944 {
945        if (! -r $config_file) {
946                print STDERR "file '$config_file' is not readable or does not exist\n";
947                exit 2;
948        }
949 
950        if (!open(CONFIG_FILE, "<", "$config_file")) {
951                print STDERR "open $config_file failed\n";
952                exit 2;
953        }
954 
955        my @line;
956 
957        LINE:
958        while ($line = <CONFIG_FILE>) {
959                chomp($line);
960                next LINE if ($line =~ /^\s*#/);
961                next LINE if ($line =~ /^\s*$/);
962                @line = split /=/, $line;
963                $existing_config{@line[0]} = @line[1];
964        }
965 
966        close(CONFIG_FILE);
967 }
968 
969 
970 sub cmd_line_err()
971 {
972        my $msg = shift;
973 
974        print STDERR "\n";
975        print STDERR "   ERROR processing command line options\n";
976        print STDERR "         $msg\n" if ($msg ne "");
977        print STDERR "\n";
978        print STDERR "   For help, type '$script_name --help'\n";
979        print STDERR "\n";
980 }
981 
982 
983 # -----------------------------------------------------------------------------
984 # program entry point
985 
986 Getopt::Long::Configure("no_ignore_case", "bundling");
987 
988 if (!GetOptions(
989        "c=s"               => \$config_file,
990        "config=s"          => \$config_file,
991        "config-format"     => \$config_format,
992        "exclude-flag=s"    => \@exclude_flag,
993        "h"                 => \$help,
994        "help"              => \$help,
995        "black-list-driver" => \$black_list_driver,
996        "white-list-config" => \$white_list_config,
997        "white-list-driver" => \$white_list_driver,
998        "include-flag=s"    => \@include_flag,
999        "include-suspect"   => \$include_suspect,
1000        "short-name"        => \$short_name,
1001        "show-lists"        => \$show_lists,
1002        "version"           => \$version,
1003        )) {
1004 
1005        &cmd_line_err();
1006 
1007        exit 1;
1008 }
1009 
1010 
1011 my $exit_after_messages = 0;
1012 
1013 if ($version) {
1014        print STDERR "\n$script_name  $VUFX\n\n";
1015        $exit_after_messages = 1;
1016 }
1017 
1018 
1019 if ($help) {
1020        &usage;
1021        $exit_after_messages = 1;
1022 }
1023 
1024 
1025 if ($show_lists) {
1026 
1027        print "\n";
1028        print "These compatibles are hard coded to have no driver.\n";
1029        print "\n";
1030        for my $compat (sort keys %compat_white_list) {
1031                print "   $compat\n";
1032        }
1033 
1034 
1035        print "\n\n";
1036        print "The driver for these compatibles is hard coded (white list).\n";
1037        print "\n";
1038        my $max_compat_len = 0;
1039        for my $compat (sort keys %driver_hard_code_list) {
1040                if (length $compat > $max_compat_len) {
1041                        $max_compat_len = length $compat;
1042                }
1043        }
1044        for my $compat (sort keys %driver_hard_code_list) {
1045                if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
1046                        my $first = 1;
1047                        for my $driver (@{ $driver_hard_code_list{$compat} }) {
1048                                if ($first) {
1049                                        print "   $compat";
1050                                        print " " x ($max_compat_len - length $compat);
1051                                        $first = 0;
1052                                } else {
1053                                        print "   ", " " x $max_compat_len;
1054                                }
1055                                print "  $driver\n";
1056                        }
1057                }
1058        }
1059 
1060 
1061        print "\n\n";
1062        print "The configuration option for these drivers is hard coded (white list).\n";
1063        print "\n";
1064        my $max_driver_len = 0;
1065        for my $driver (sort keys %driver_config_hard_code_list) {
1066                if (length $driver > $max_driver_len) {
1067                        $max_driver_len = length $driver;
1068                }
1069        }
1070        for my $driver (sort keys %driver_config_hard_code_list) {
1071                if (($driver ne "hardcoded_no_driver") && ($driver ne "no_driver")) {
1072                        my $first = 1;
1073                        for my $config (@{ $driver_config_hard_code_list{$driver} }) {
1074                                if ($first) {
1075                                        print "   $driver";
1076                                        print " " x ($max_driver_len - length $driver);
1077                                        $first = 0;
1078                                } else {
1079                                        print "   ", " " x $max_driver_len;
1080                                }
1081                                print "  $config\n";
1082                        }
1083                }
1084        }
1085 
1086 
1087        print "\n\n";
1088        print "These drivers are black listed.\n";
1089        print "\n";
1090        for my $driver (@black_list_driver) {
1091                print "   $driver\n";
1092        }
1093 
1094        print "\n";
1095 
1096        $exit_after_messages = 1;
1097 }
1098 
1099 
1100 if ($exit_after_messages) {
1101        exit 0;
1102 }
1103 
1104 
1105 $exclude_flag_pattern = "[";
1106 for my $exclude_flag (@exclude_flag) {
1107        $exclude_flag_pattern = $exclude_flag_pattern . $exclude_flag;
1108 }
1109 $exclude_flag_pattern = $exclude_flag_pattern . "]";
1110 # clean up if empty
1111 $exclude_flag_pattern =~ s/^\[\]$//;
1112 
1113 
1114 $include_flag_pattern = "[";
1115 for my $include_flag (@include_flag) {
1116        $include_flag_pattern = $include_flag_pattern . $include_flag;
1117 }
1118 $include_flag_pattern = $include_flag_pattern . "]";
1119 # clean up if empty
1120 $include_flag_pattern =~ s/^\[\]$//;
1121 
1122 
1123 if ($exclude_flag_pattern) {
1124        my $found = 0;
1125        for $pr_flag_value (@pr_flag_value) {
1126                if ($exclude_flag_pattern =~ m/$pr_flag_value/) {
1127                        $found = 1;
1128                }
1129        }
1130        if (!$found) {
1131                &cmd_line_err("invalid value for FLAG in --exclude-flag\n");
1132                exit 1
1133        }
1134 }
1135 
1136 if ($include_flag_pattern) {
1137        my $found = 0;
1138        for $pr_flag_value (@pr_flag_value) {
1139                if ($include_flag_pattern =~ m/$pr_flag_value/) {
1140                        $found = 1;
1141                }
1142        }
1143        if (!$found) {
1144                &cmd_line_err("invalid value for FLAG in --include-flag\n");
1145                exit 1
1146        }
1147 }
1148 
1149 if ($include_suspect) {
1150        $include_flag_pattern =~ s/\[//;
1151        $include_flag_pattern =~ s/\]//;
1152        $include_flag_pattern = "[" . $include_flag_pattern . "A-Z]";
1153 }
1154 
1155 if ($exclude_flag_pattern =~ m/$include_flag_pattern/) {
1156        &cmd_line_err("the same flag appears in both --exclude-flag and --include-flag or --include-suspect\n");
1157        exit 1
1158 }
1159 
1160 
1161 # ($#ARGV < 0) is valid for --help, --version
1162 if ($#ARGV < 0) {
1163        &cmd_line_err("device-tree... is required");
1164        exit 1
1165 }
1166 
1167 
1168 if ($config_file) {
1169        &read_config_file();
1170 }
1171 
1172 
1173 # avoid pushing duplicates for this value
1174 $driver = "hardcoded_no_driver";
1175 for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
1176        push @{ $driver_config{$driver} }, $config;
1177 }
1178 
1179 if ($white_list_driver) {
1180        for my $compat (keys %driver_hard_code_list) {
1181                for my $driver (@{ $driver_hard_code_list{$compat} }) {
1182                        push @{ $compat_driver{$compat} }, $driver;
1183                        if ($driver ne "hardcoded_no_driver") {
1184                                $driver_count{$compat} = scalar @{ $compat_driver{$compat} };
1185                        }
1186                }
1187        }
1188 }
1189 
1190 if ($white_list_config) {
1191        for my $driver (keys %driver_config_hard_code_list) {
1192                if ($driver ne "hardcoded_no_driver") {
1193                        for $config ( @{ $driver_config_hard_code_list{$driver} } ) {
1194                                push @{ $driver_config{$driver} }, $config;
1195                        }
1196                }
1197        }
1198 }
1199 
1200 if (-x "scripts/dtc/dtx_diff") {
1201        $dtx_diff = "scripts/dtc/dtx_diff";
1202 } else {
1203 
1204        print STDERR "\n";
1205        print STDERR "$script_name must be run from the root directory of a Linux kernel tree\n";
1206        print STDERR "\n";
1207        exit 3;
1208 }
1209 
1210 for $file (@ARGV) {
1211        &read_dts($file);
1212 }

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php