1# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2022 Google LLC
3#
4"""Bintool implementation for fdtgrep
5
6fdtgrepprovides a way to grep devicetree-binary files to extract or remove
7certain elements.
8
9Usage: fdtgrep - extract portions from device tree
10
11Usage:
12	fdtgrep <options> <dt file>|-
13
14Output formats are:
15	dts - device tree soure text
16	dtb - device tree blob (sets -Hmt automatically)
17	bin - device tree fragment (may not be a valid .dtb)
18
19Options: -[haAc:b:C:defg:G:HIlLmn:N:o:O:p:P:rRsStTvhV]
20  -a, --show-address                 Display address
21  -A, --colour                       Show all nodes/tags, colour those that match
22  -b, --include-node-with-prop <arg> Include contains containing property
23  -c, --include-compat <arg>         Compatible nodes to include in grep
24  -C, --exclude-compat <arg>         Compatible nodes to exclude in grep
25  -d, --diff                         Diff: Mark matching nodes with +, others with -
26  -e, --enter-node                   Enter direct subnode names of matching nodes
27  -f, --show-offset                  Display offset
28  -g, --include-match <arg>          Node/property/compatible string to include in grep
29  -G, --exclude-match <arg>          Node/property/compatible string to exclude in grep
30  -H, --show-header                  Output a header
31  -I, --show-version                 Put "/dts-v1/;" on first line of dts output
32  -l, --list-regions                 Output a region list
33  -L, --list-strings                 List strings in string table
34  -m, --include-mem                  Include mem_rsvmap section in binary output
35  -n, --include-node <arg>           Node to include in grep
36  -N, --exclude-node <arg>           Node to exclude in grep
37  -p, --include-prop <arg>           Property to include in grep
38  -P, --exclude-prop <arg>           Property to exclude in grep
39  -r, --remove-strings               Remove unused strings from string table
40  -R, --include-root                 Include root node and all properties
41  -s, --show-subnodes                Show all subnodes matching nodes
42  -S, --skip-supernodes              Don't include supernodes of matching nodes
43  -t, --show-stringtab               Include string table in binary output
44  -T, --show-aliases                 Include matching aliases in output
45  -o, --out <arg>                    -o <output file>
46  -O, --out-format <arg>             -O <output format>
47  -v, --invert-match                 Invert the sense of matching (select non-matching lines)
48  -h, --help                         Print this help and exit
49  -V, --version                      Print version and exit
50"""
51
52import tempfile
53
54from u_boot_pylib import tools
55from binman import bintool
56
57class Bintoolfdtgrep(bintool.Bintool):
58    """Handles the 'fdtgrep' tool
59
60    This bintool supports running `fdtgrep` with parameters suitable for
61    producing SPL devicetrees from the main one.
62    """
63    def __init__(self, name):
64        super().__init__(name, 'Grep devicetree files')
65
66    def create_for_phase(self, infile, phase, outfile, remove_props):
67        """Create the FDT for a particular phase
68
69        Args:
70            infile (str): Input filename containing the full FDT contents (with
71                all nodes and properties)
72            phase (str): Phase to generate for ('tpl', 'vpl', 'spl')
73            outfile (str): Output filename to write the grepped FDT contents to
74                (with only neceesary nodes and properties)
75
76        Returns:
77            str or bytes: Resulting stdout from the bintool
78        """
79        if phase == 'tpl':
80            tag = 'bootph-pre-sram'
81        elif phase == 'vpl':
82            tag = 'bootph-verify'
83        elif phase == 'spl':
84            tag = 'bootph-pre-ram'
85        else:
86            raise ValueError(f"Invalid U-Boot phase '{phase}': Use tpl/vpl/spl")
87
88        # These args mirror those in cmd_fdtgrep in scripts/Makefile.lib
89        # First do the first stage
90        with tempfile.NamedTemporaryFile(prefix='fdtgrep.tmp',
91                                         dir=tools.get_output_dir()) as tmp:
92            args = [
93                infile,
94                '-o', tmp.name,
95                '-b', 'bootph-all',
96                '-b', tag,
97                '-u',
98                '-RT',
99                '-n', '/chosen',
100                 '-n', '/config',
101                 '-O', 'dtb',
102                ]
103            self.run_cmd(*args)
104            args = [
105                    tmp.name,
106                    '-o', outfile,
107                    '-r',
108                     '-O', 'dtb',
109                    '-P', 'bootph-all',
110                    '-P', 'bootph-pre-ram',
111                    '-P', 'bootph-pre-sram',
112                    '-P', 'bootph-verify',
113                    ]
114            for prop_name in remove_props:
115                args += ['-P', prop_name]
116            return self.run_cmd(*args)
117
118    def fetch(self, method):
119        """Fetch handler for fdtgrep
120
121        This installs fdtgrep using the apt utility, which assumes that it is
122        packaged in u-boot tools, which it is not.
123
124        Args:
125            method (FETCH_...): Method to use
126
127        Returns:
128            True if the file was fetched and now installed, None if a method
129            other than FETCH_BIN was requested
130
131        Raises:
132            Valuerror: Fetching could not be completed
133        """
134        if method != bintool.FETCH_BIN:
135            return None
136        return self.apt_install('u-boot-tools')
137