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