1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2018 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 """# Entry-type module for a full map of the firmware image
7 This handles putting an FDT into the image with just the information about the
11 from binman.entry import Entry
12 from u_boot_pylib import tools
13 from u_boot_pylib import tout
15 FDTMAP_MAGIC = b'_FDTMAP_'
18 # These is imported if needed
23 def LocateFdtmap(data):
24 """Search an image for an fdt map
30 Position of fdt map in data, or None if not found. Note that the
31 position returned is of the FDT header, i.e. before the FDT data
33 hdr_pos = data.find(FDTMAP_MAGIC)
36 hdr = data[hdr_pos:hdr_pos + FDTMAP_HDR_LEN]
37 if len(hdr) == FDTMAP_HDR_LEN:
41 class Entry_fdtmap(Entry):
42 """An entry which contains an FDT map
44 Properties / Entry arguments:
47 An FDT map is just a header followed by an FDT containing a list of all the
48 entries in the image. The root node corresponds to the image node in the
49 original FDT, and an image-name property indicates the image name in that
52 The header is the string _FDTMAP_ followed by 8 unused bytes.
54 When used, this entry will be populated with an FDT map which reflects the
55 entries in the current image. Hierarchy is preserved, and all offsets and
58 Note that the -u option must be provided to ensure that binman updates the
59 FDT with the position of each entry.
61 Example output for a simple image with U-Boot and an FDT map::
64 image-name = "binman";
66 image-pos = <0x00000000>;
67 offset = <0x00000000>;
70 image-pos = <0x00000000>;
71 offset = <0x00000000>;
75 image-pos = <0x00000004>;
76 offset = <0x00000004>;
80 If allow-repack is used then 'orig-offset' and 'orig-size' properties are
81 added as necessary. See the binman README.
83 When extracting files, an alternative 'fdt' format is available for fdtmaps.
84 Use `binman extract -F fdt ...` to use this. It will export a devicetree,
85 without the fdtmap header, so it can be viewed with `fdtdump`.
87 def __init__(self, section, etype, node):
88 # Put these here to allow entry-docs and help to work without libfdt
94 from binman import state
95 from dtoc.fdt import Fdt
97 super().__init__(section, etype, node)
98 self.alt_formats = ['fdt']
100 def CheckAltFormats(self, alt_formats):
101 alt_formats['fdt'] = self, 'Extract the devicetree blob from the fdtmap'
103 def _GetFdtmap(self):
104 """Build an FDT map from the entries in the current image
110 """Add a node to the FDT map"""
111 for pname, prop in node.props.items():
112 fsw.property(pname, prop.bytes)
113 for subnode in node.subnodes:
114 with fsw.add_node(subnode.name):
117 data = state.GetFdtContents('fdtmap')[1]
118 # If we have an fdtmap it means that we are using this as the
119 # fdtmap for this image.
121 # Get the FDT data into an Fdt object
122 data = state.GetFdtContents()[1]
123 infdt = Fdt.FromData(data)
126 # Find the node for the image containing the Fdt-map entry
127 path = self.section.GetPath()
128 self.Detail("Fdtmap: Using section '%s' (path '%s')" %
129 (self.section.name, path))
130 node = infdt.GetNode(path)
132 self.Raise("Internal error: Cannot locate node for path '%s'" %
135 # Build a new tree with all nodes and properties starting from that
138 fsw.finish_reservemap()
139 with fsw.add_node(''):
140 fsw.property_string('image-node', node.name)
144 # Pack this new FDT and return its contents
146 outfdt = Fdt.FromData(fdt.as_bytearray())
147 data = outfdt.GetContents()
148 data = FDTMAP_MAGIC + tools.get_bytes(0, 8) + data
151 def ObtainContents(self):
152 """Obtain a placeholder for the fdt-map contents"""
153 self.SetContents(self._GetFdtmap())
156 def ProcessContents(self):
157 """Write an updated version of the FDT map to this entry
159 This is necessary since new data may have been written back to it during
160 processing, e.g. the image-pos properties.
162 return self.ProcessContentsUpdate(self._GetFdtmap())
164 def GetAltFormat(self, data, alt_format):
165 if alt_format == 'fdt':
166 return data[FDTMAP_HDR_LEN:]