binman: Add a return value to ProcessContentsUpdate()
[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 import libfdt
12
13 from entry import Entry
14 from fdt import Fdt
15 import state
16 import tools
17
18 FDTMAP_MAGIC = b'_FDTMAP_'
19
20 class Entry_fdtmap(Entry):
21     """An entry which contains an FDT map
22
23     Properties / Entry arguments:
24         None
25
26     An FDT map is just a header followed by an FDT containing a list of all the
27     entries in the image.
28
29     The header is the string _FDTMAP_ followed by 8 unused bytes.
30
31     When used, this entry will be populated with an FDT map which reflects the
32     entries in the current image. Hierarchy is preserved, and all offsets and
33     sizes are included.
34
35     Note that the -u option must be provided to ensure that binman updates the
36     FDT with the position of each entry.
37
38     Example output for a simple image with U-Boot and an FDT map:
39
40     / {
41         size = <0x00000112>;
42         image-pos = <0x00000000>;
43         offset = <0x00000000>;
44         u-boot {
45             size = <0x00000004>;
46             image-pos = <0x00000000>;
47             offset = <0x00000000>;
48         };
49         fdtmap {
50             size = <0x0000010e>;
51             image-pos = <0x00000004>;
52             offset = <0x00000004>;
53         };
54     };
55     """
56     def __init__(self, section, etype, node):
57         Entry.__init__(self, section, etype, node)
58
59     def _GetFdtmap(self):
60         """Build an FDT map from the entries in the current image
61
62         Returns:
63             FDT map binary data
64         """
65         def _AddNode(node):
66             """Add a node to the FDT map"""
67             for pname, prop in node.props.items():
68                 fsw.property(pname, prop.bytes)
69             for subnode in node.subnodes:
70                 with fsw.add_node(subnode.name):
71                     _AddNode(subnode)
72
73         # Get the FDT data into an Fdt object
74         data = state.GetFdtContents()[1]
75         infdt = Fdt.FromData(data)
76         infdt.Scan()
77
78         # Find the node for the image containing the Fdt-map entry
79         path = self.section.GetPath()
80         node = infdt.GetNode(path)
81         if not node:
82             self.Raise("Internal error: Cannot locate node for path '%s'" %
83                        path)
84
85         # Build a new tree with all nodes and properties starting from that node
86         fsw = libfdt.FdtSw()
87         fsw.finish_reservemap()
88         with fsw.add_node(''):
89             _AddNode(node)
90         fdt = fsw.as_fdt()
91
92         # Pack this new FDT and return its contents
93         fdt.pack()
94         outfdt = Fdt.FromData(fdt.as_bytearray())
95         data = FDTMAP_MAGIC + tools.GetBytes(0, 8) + outfdt.GetContents()
96         return data
97
98     def ObtainContents(self):
99         """Obtain a placeholder for the fdt-map contents"""
100         self.SetContents(self._GetFdtmap())
101         return True
102
103     def ProcessContents(self):
104         """Write an updated version of the FDT map to this entry
105
106         This is necessary since new data may have been written back to it during
107         processing, e.g. the image-pos properties.
108         """
109         return self.ProcessContentsUpdate(self._GetFdtmap())