ARM: dts: at91: sama7g5ek: disable slew rate for GMACs non MDIO pins
[platform/kernel/u-boot.git] / tools / binman / etype / atf_fip.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright 2019 Google LLC
3 # Written by Simon Glass <sjg@chromium.org>
4 #
5 # Entry-type module for the ARM Trusted Firmware's Firmware Image Package (FIP)
6 # format
7
8 from collections import OrderedDict
9
10 from binman.entry import Entry
11 from binman.etype.section import Entry_section
12 from binman.fip_util import FIP_TYPES, FipReader, FipWriter, UUID_LEN
13 from dtoc import fdt_util
14 from patman import tools
15
16 class Entry_atf_fip(Entry_section):
17     """ARM Trusted Firmware's Firmware Image Package (FIP)
18
19     A FIP_ provides a way to group binaries in a firmware image, used by ARM's
20     Trusted Firmware A (TF-A) code. It is a simple format consisting of a
21     table of contents with information about the type, offset and size of the
22     binaries in the FIP. It is quite similar to FMAP, with the major difference
23     that it uses UUIDs to indicate the type of each entry.
24
25     Note: It is recommended to always add an fdtmap to every image, as well as
26     any FIPs so that binman and other tools can access the entire image
27     correctly.
28
29     The UUIDs correspond to useful names in `fiptool`, provided by ATF to
30     operate on FIPs. Binman uses these names to make it easier to understand
31     what is going on, although it is possible to provide a UUID if needed.
32
33     The contents of the FIP are defined by subnodes of the atf-fip entry, e.g.::
34
35         atf-fip {
36             soc-fw {
37                 filename = "bl31.bin";
38             };
39
40             scp-fwu-cfg {
41                 filename = "bl2u.bin";
42             };
43
44             u-boot {
45                 fip-type = "nt-fw";
46             };
47         };
48
49     This describes a FIP with three entries: soc-fw, scp-fwu-cfg and nt-fw.
50     You can use normal (non-external) binaries like U-Boot simply by adding a
51     FIP type, with the `fip-type` property, as above.
52
53     Since FIP exists to bring blobs together, Binman assumes that all FIP
54     entries are external binaries. If a binary may not exist, you can use the
55     `--allow-missing` flag to Binman, in which case the image is still created,
56     even though it will not actually work.
57
58     The size of the FIP depends on the size of the binaries. There is currently
59     no way to specify a fixed size. If the `atf-fip` node has a `size` entry,
60     this affects the space taken up by the `atf-fip` entry, but the FIP itself
61     does not expand to use that space.
62
63     Some other FIP features are available with Binman. The header and the
64     entries have 64-bit flag works. The flag flags do not seem to be defined
65     anywhere, but you can use `fip-hdr-flags` and fip-flags` to set the values
66     of the header and entries respectively.
67
68     FIP entries can be aligned to a particular power-of-two boundary. Use
69     fip-align for this.
70
71     Binman only understands the entry types that are included in its
72     implementation. It is possible to specify a 16-byte UUID instead, using the
73     fip-uuid property. In this case Binman doesn't know what its type is, so
74     just uses the UUID. See the `u-boot` node in this example::
75
76         binman {
77             atf-fip {
78                 fip-hdr-flags = /bits/ 64 <0x123>;
79                 fip-align = <16>;
80                 soc-fw {
81                     fip-flags = /bits/ 64 <0x456>;
82                     filename = "bl31.bin";
83                 };
84
85                 scp-fwu-cfg {
86                     filename = "bl2u.bin";
87                 };
88
89                 u-boot {
90                     fip-uuid = [fc 65 13 92 4a 5b 11 ec
91                                 94 35 ff 2d 1c fc 79 9c];
92                 };
93             };
94             fdtmap {
95             };
96         };
97
98     Binman allows reading and updating FIP entries after the image is created,
99     provided that an FDPMAP is present too. Updates which change the size of a
100     FIP entry will cause it to be expanded or contracted as needed.
101
102     Properties for top-level atf-fip node
103     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
104
105     fip-hdr-flags (64 bits)
106         Sets the flags for the FIP header.
107
108     Properties for subnodes
109     ~~~~~~~~~~~~~~~~~~~~~~~
110
111     fip-type (str)
112         FIP type to use for this entry. This is needed if the entry
113         name is not a valid type. Value types are defined in `fip_util.py`.
114         The FIP type defines the UUID that is used (they map 1:1).
115
116     fip-uuid (16 bytes)
117         If there is no FIP-type name defined, or it is not supported by Binman,
118         this property sets the UUID. It should be a 16-byte value, following the
119         hex digits of the UUID.
120
121     fip-flags (64 bits)
122         Set the flags for a FIP entry. Use in one of the subnodes of the
123         7atf-fip entry.
124
125     fip-align
126         Set the alignment for a FIP entry, FIP entries can be aligned to a
127         particular power-of-two boundary. The default is 1.
128
129     Adding new FIP-entry types
130     ~~~~~~~~~~~~~~~~~~~~~~~~~~
131
132     When new FIP entries are defined by TF-A they appear in the
133     `TF-A source tree`_. You can use `fip_util.py` to update Binman to support
134     new types, then `send a patch`_ to the U-Boot mailing list. There are two
135     source files that the tool examples:
136
137     - `include/tools_share/firmware_image_package.h` has the UUIDs
138     - `tools/fiptool/tbbr_config.c` has the name and descripion for each UUID
139
140     To run the tool::
141
142         $ tools/binman/fip_util.py  -s /path/to/arm-trusted-firmware
143         Warning: UUID 'UUID_NON_TRUSTED_WORLD_KEY_CERT' is not mentioned in tbbr_config.c file
144         Existing code in 'tools/binman/fip_util.py' is up-to-date
145
146     If it shows there is an update, it writes a new version of `fip_util.py`
147     to `fip_util.py.out`. You can change the output file using the `-i` flag.
148     If you have a problem, use `-D` to enable traceback debugging.
149
150     FIP commentary
151     ~~~~~~~~~~~~~~
152
153     As a side effect of use of UUIDs, FIP does not support multiple
154     entries of the same type, such as might be used to store fonts or graphics
155     icons, for example. For verified boot it could be used for each part of the
156     image (e.g. separate FIPs for A and B) but cannot describe the whole
157     firmware image. As with FMAP there is no hierarchy defined, although FMAP
158     works around this by having 'section' areas which encompass others. A
159     similar workaround would be possible with FIP but is not currently defined.
160
161     It is recommended to always add an fdtmap to every image, as well as any
162     FIPs so that binman and other tools can access the entire image correctly.
163
164     .. _FIP: https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#firmware-image-package-fip
165     .. _`TF-A source tree`: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
166     .. _`send a patch`: https://www.denx.de/wiki/U-Boot/Patches
167     """
168     def __init__(self, section, etype, node):
169         # Put this here to allow entry-docs and help to work without libfdt
170         global state
171         from binman import state
172
173         super().__init__(section, etype, node)
174         self.align_default = None
175         self._entries = OrderedDict()
176         self.reader = None
177
178     def ReadNode(self):
179         """Read properties from the atf-fip node"""
180         super().ReadNode()
181         self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
182         self._fip_flags = fdt_util.GetInt64(self._node, 'fip-hdr-flags', 0)
183         self._fip_align = fdt_util.GetInt(self._node, 'fip-align', 1)
184         if tools.NotPowerOfTwo(self._fip_align):
185             raise ValueError("Node '%s': FIP alignment %s must be a power of two" %
186                              (self._node.path, self._fip_align))
187         self.ReadEntries()
188
189     def ReadEntries(self):
190         """Read the subnodes to find out what should go in this FIP"""
191         for node in self._node.subnodes:
192             fip_type = None
193             etype = None
194             if node.name in FIP_TYPES:
195                 fip_type = node.name
196                 etype = 'blob-ext'
197
198             entry = Entry.Create(self, node, etype)
199             entry._fip_uuid = fdt_util.GetBytes(node, 'fip-uuid', UUID_LEN)
200             if not fip_type and not entry._fip_uuid:
201                 fip_type = fdt_util.GetString(node, 'fip-type')
202                 if not fip_type:
203                     self.Raise("Must provide a fip-type (node name '%s' is not a known FIP type)" %
204                                node.name)
205
206             entry._fip_type = fip_type
207             entry._fip_flags = fdt_util.GetInt64(node, 'fip-flags', 0)
208             entry.ReadNode()
209             entry._fip_name = node.name
210             self._entries[entry._fip_name] = entry
211
212     def BuildSectionData(self, required):
213         """Override this function to create a custom format for the entries
214
215         Arguments:
216             required (bool): True if the data must be valid, False if it may
217                 be missing (entry.GetData() returns None
218
219         Returns:
220             bytes: Data obtained, or None if None
221         """
222         fip = FipWriter(self._fip_flags, self._fip_align)
223         for entry in self._entries.values():
224             # First get the input data and put it in an entry. If not available,
225             # try later.
226             entry_data = entry.GetData(required)
227             if not required and entry_data is None:
228                 return None
229             fent = fip.add_entry(entry._fip_type or entry._fip_uuid, entry_data,
230                                  entry._fip_flags)
231             if fent:
232                 entry._fip_entry = fent
233         data = fip.get_data()
234         return data
235
236     def SetImagePos(self, image_pos):
237         """Override this function to set all the entry properties from FIP
238
239         We can only do this once image_pos is known
240
241         Args:
242             image_pos: Position of this entry in the image
243         """
244         super().SetImagePos(image_pos)
245
246         # Now update the entries with info from the FIP entries
247         for entry in self._entries.values():
248             fent = entry._fip_entry
249             entry.size = fent.size
250             entry.offset = fent.offset
251             entry.image_pos = self.image_pos + entry.offset
252
253     def ReadChildData(self, child, decomp=True, alt_format=None):
254         if not self.reader:
255             self.fip_data = super().ReadData(True)
256             self.reader = FipReader(self.fip_data)
257         reader = self.reader
258
259         # It is tricky to obtain the data from a FIP entry since it is indexed
260         # by its UUID.
261         fent = reader.get_entry(child._fip_type or child._fip_uuid)
262         return fent.data
263
264         # Note:
265         # It is also possible to extract it using the offsets directly, but this
266         # seems less FIP_friendly:
267         # return self.fip_data[child.offset:child.offset + child.size]
268
269     def WriteChildData(self, child):
270         # Recreate the data structure, leaving the data for this child alone,
271         # so that child.data is used to pack into the FIP.
272         self.ObtainContents(skip_entry=child)
273         return True