binman: Add a return value to ProcessContentsUpdate()
[oweals/u-boot.git] / tools / binman / image.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
4 #
5 # Class for an image, the output of binman
6 #
7
8 from __future__ import print_function
9
10 from collections import OrderedDict
11 from operator import attrgetter
12 import re
13 import sys
14
15 import fdt_util
16 import bsection
17 import tools
18
19 class Image:
20     """A Image, representing an output from binman
21
22     An image is comprised of a collection of entries each containing binary
23     data. The image size must be large enough to hold all of this data.
24
25     This class implements the various operations needed for images.
26
27     Atrtributes:
28         _node: Node object that contains the image definition in device tree
29         _name: Image name
30         _size: Image size in bytes, or None if not known yet
31         _filename: Output filename for image
32         _sections: Sections present in this image (may be one or more)
33
34     Args:
35         test: True if this is being called from a test of Images. This this case
36             there is no device tree defining the structure of the section, so
37             we create a section manually.
38     """
39     def __init__(self, name, node, test=False):
40         self._node = node
41         self._name = name
42         self._size = None
43         self._filename = '%s.bin' % self._name
44         if test:
45             self._section = bsection.Section('main-section', None, self._node,
46                                              self, True)
47         else:
48             self._ReadNode()
49
50     def _ReadNode(self):
51         """Read properties from the image node"""
52         self._size = fdt_util.GetInt(self._node, 'size')
53         filename = fdt_util.GetString(self._node, 'filename')
54         if filename:
55             self._filename = filename
56         self._section = bsection.Section('main-section', None, self._node, self)
57
58     def GetFdtSet(self):
59         """Get the set of device tree files used by this image"""
60         return self._section.GetFdtSet()
61
62     def ExpandEntries(self):
63         """Expand out any entries which have calculated sub-entries
64
65         Some entries are expanded out at runtime, e.g. 'files', which produces
66         a section containing a list of files. Process these entries so that
67         this information is added to the device tree.
68         """
69         self._section.ExpandEntries()
70
71     def AddMissingProperties(self):
72         """Add properties that are not present in the device tree
73
74         When binman has completed packing the entries the offset and size of
75         each entry are known. But before this the device tree may not specify
76         these. Add any missing properties, with a dummy value, so that the
77         size of the entry is correct. That way we can insert the correct values
78         later.
79         """
80         self._section.AddMissingProperties()
81
82     def ProcessFdt(self, fdt):
83         """Allow entries to adjust the device tree
84
85         Some entries need to adjust the device tree for their purposes. This
86         may involve adding or deleting properties.
87         """
88         return self._section.ProcessFdt(fdt)
89
90     def GetEntryContents(self):
91         """Call ObtainContents() for the section
92         """
93         self._section.GetEntryContents()
94
95     def GetEntryOffsets(self):
96         """Handle entries that want to set the offset/size of other entries
97
98         This calls each entry's GetOffsets() method. If it returns a list
99         of entries to update, it updates them.
100         """
101         self._section.GetEntryOffsets()
102
103     def PackEntries(self):
104         """Pack all entries into the image"""
105         self._section.PackEntries()
106
107     def CheckSize(self):
108         """Check that the image contents does not exceed its size, etc."""
109         self._size = self._section.CheckSize()
110
111     def CheckEntries(self):
112         """Check that entries do not overlap or extend outside the image"""
113         self._section.CheckEntries()
114
115     def SetCalculatedProperties(self):
116         self._section.SetCalculatedProperties()
117
118     def SetImagePos(self):
119         self._section.SetImagePos(0)
120
121     def ProcessEntryContents(self):
122         """Call the ProcessContents() method for each entry
123
124         This is intended to adjust the contents as needed by the entry type.
125
126         Returns:
127             True if the new data size is OK, False if expansion is needed
128         """
129         return self._section.ProcessEntryContents()
130
131     def WriteSymbols(self):
132         """Write symbol values into binary files for access at run time"""
133         self._section.WriteSymbols()
134
135     def BuildImage(self):
136         """Write the image to a file"""
137         fname = tools.GetOutputFilename(self._filename)
138         with open(fname, 'wb') as fd:
139             self._section.BuildSection(fd, 0)
140
141     def GetEntries(self):
142         return self._section.GetEntries()
143
144     def WriteMap(self):
145         """Write a map of the image to a .map file
146
147         Returns:
148             Filename of map file written
149         """
150         filename = '%s.map' % self._name
151         fname = tools.GetOutputFilename(filename)
152         with open(fname, 'w') as fd:
153             print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
154                   file=fd)
155             self._section.WriteMap(fd, 0)
156         return fname