rockchip: rk3399: Add Nanopi M4 2GB board support
[platform/kernel/u-boot.git] / tools / binman / etype / fdtmap.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2018 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
4
5 """# Entry-type module for a full map of the firmware image
6
7 This handles putting an FDT into the image with just the information about the
8 image.
9 """
10
11 from entry import Entry
12 import tools
13 import tout
14
15 FDTMAP_MAGIC   = b'_FDTMAP_'
16 FDTMAP_HDR_LEN = 16
17
18 def LocateFdtmap(data):
19     """Search an image for an fdt map
20
21     Args:
22         data: Data to search
23
24     Returns:
25         Position of fdt map in data, or None if not found. Note that the
26             position returned is of the FDT header, i.e. before the FDT data
27     """
28     hdr_pos = data.find(FDTMAP_MAGIC)
29     size = len(data)
30     if hdr_pos != -1:
31         hdr = data[hdr_pos:hdr_pos + FDTMAP_HDR_LEN]
32         if len(hdr) == FDTMAP_HDR_LEN:
33             return hdr_pos
34     return None
35
36 class Entry_fdtmap(Entry):
37     """An entry which contains an FDT map
38
39     Properties / Entry arguments:
40         None
41
42     An FDT map is just a header followed by an FDT containing a list of all the
43     entries in the image. The root node corresponds to the image node in the
44     original FDT, and an image-name property indicates the image name in that
45     original tree.
46
47     The header is the string _FDTMAP_ followed by 8 unused bytes.
48
49     When used, this entry will be populated with an FDT map which reflects the
50     entries in the current image. Hierarchy is preserved, and all offsets and
51     sizes are included.
52
53     Note that the -u option must be provided to ensure that binman updates the
54     FDT with the position of each entry.
55
56     Example output for a simple image with U-Boot and an FDT map:
57
58     / {
59         image-name = "binman";
60         size = <0x00000112>;
61         image-pos = <0x00000000>;
62         offset = <0x00000000>;
63         u-boot {
64             size = <0x00000004>;
65             image-pos = <0x00000000>;
66             offset = <0x00000000>;
67         };
68         fdtmap {
69             size = <0x0000010e>;
70             image-pos = <0x00000004>;
71             offset = <0x00000004>;
72         };
73     };
74
75     If allow-repack is used then 'orig-offset' and 'orig-size' properties are
76     added as necessary. See the binman README.
77     """
78     def __init__(self, section, etype, node):
79         # Put these here to allow entry-docs and help to work without libfdt
80         global libfdt
81         global state
82         global Fdt
83
84         import libfdt
85         import state
86         from fdt import Fdt
87
88         Entry.__init__(self, section, etype, node)
89
90     def _GetFdtmap(self):
91         """Build an FDT map from the entries in the current image
92
93         Returns:
94             FDT map binary data
95         """
96         def _AddNode(node):
97             """Add a node to the FDT map"""
98             for pname, prop in node.props.items():
99                 fsw.property(pname, prop.bytes)
100             for subnode in node.subnodes:
101                 with fsw.add_node(subnode.name):
102                     _AddNode(subnode)
103
104         data = state.GetFdtContents('fdtmap')[1]
105         # If we have an fdtmap it means that we are using this as the
106         # fdtmap for this image.
107         if data is None:
108             # Get the FDT data into an Fdt object
109             data = state.GetFdtContents()[1]
110             infdt = Fdt.FromData(data)
111             infdt.Scan()
112
113             # Find the node for the image containing the Fdt-map entry
114             path = self.section.GetPath()
115             self.Detail("Fdtmap: Using section '%s' (path '%s')" %
116                         (self.section.name, path))
117             node = infdt.GetNode(path)
118             if not node:
119                 self.Raise("Internal error: Cannot locate node for path '%s'" %
120                            path)
121
122             # Build a new tree with all nodes and properties starting from that
123             # node
124             fsw = libfdt.FdtSw()
125             fsw.finish_reservemap()
126             with fsw.add_node(''):
127                 fsw.property_string('image-node', node.name)
128                 _AddNode(node)
129             fdt = fsw.as_fdt()
130
131             # Pack this new FDT and return its contents
132             fdt.pack()
133             outfdt = Fdt.FromData(fdt.as_bytearray())
134             data = outfdt.GetContents()
135         data = FDTMAP_MAGIC + tools.GetBytes(0, 8) + data
136         return data
137
138     def ObtainContents(self):
139         """Obtain a placeholder for the fdt-map contents"""
140         self.SetContents(self._GetFdtmap())
141         return True
142
143     def ProcessContents(self):
144         """Write an updated version of the FDT map to this entry
145
146         This is necessary since new data may have been written back to it during
147         processing, e.g. the image-pos properties.
148         """
149         return self.ProcessContentsUpdate(self._GetFdtmap())