1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 # Class for an image, the output of binman
8 from __future__ import print_function
10 from collections import OrderedDict
11 from operator import attrgetter
15 from entry import Entry
16 from etype import fdtmap
17 from etype import image_header
18 from etype import section
23 class Image(section.Entry_section):
24 """A Image, representing an output from binman
26 An image is comprised of a collection of entries each containing binary
27 data. The image size must be large enough to hold all of this data.
29 This class implements the various operations needed for images.
32 filename: Output filename for image
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.
39 def __init__(self, name, node, test=False):
41 section.Entry_section.__init__(self, None, 'section', node, test)
42 self.name = 'main-section'
43 self.image_name = name
44 self._filename = '%s.bin' % self.image_name
46 filename = fdt_util.GetString(self._node, 'filename')
48 self._filename = filename
51 def FromFile(cls, fname):
52 """Convert an image file into an Image for use in binman
55 fname: Filename of image file to read
58 Image object on success
61 ValueError if something goes wrong
63 data = tools.ReadFile(fname)
66 # First look for an image header
67 pos = image_header.LocateHeaderOffset(data)
69 # Look for the FDT map
70 pos = fdtmap.LocateFdtmap(data)
72 raise ValueError('Cannot find FDT map in image')
74 # We don't know the FDT size, so check its header first
75 probe_dtb = fdt.Fdt.FromData(
76 data[pos + fdtmap.FDTMAP_HDR_LEN:pos + 256])
77 dtb_size = probe_dtb.GetFdtObj().totalsize()
78 fdtmap_data = data[pos:pos + dtb_size + fdtmap.FDTMAP_HDR_LEN]
79 dtb = fdt.Fdt.FromData(fdtmap_data[fdtmap.FDTMAP_HDR_LEN:])
82 # Return an Image with the associated nodes
83 return Image('image', dtb.GetRoot())
86 """Convenience function to raise an error referencing an image"""
87 raise ValueError("Image '%s': %s" % (self._node.path, msg))
89 def PackEntries(self):
90 """Pack all entries into the image"""
91 section.Entry_section.Pack(self, 0)
93 def SetImagePos(self):
94 # This first section in the image so it starts at 0
95 section.Entry_section.SetImagePos(self, 0)
97 def ProcessEntryContents(self):
98 """Call the ProcessContents() method for each entry
100 This is intended to adjust the contents as needed by the entry type.
103 True if the new data size is OK, False if expansion is needed
106 for entry in self._entries.values():
107 if not entry.ProcessContents():
109 print("Entry '%s' size change" % self._node.path)
112 def WriteSymbols(self):
113 """Write symbol values into binary files for access at run time"""
114 section.Entry_section.WriteSymbols(self, self)
116 def BuildSection(self, fd, base_offset):
117 """Write the section to a file"""
119 fd.write(self.GetData())
121 def BuildImage(self):
122 """Write the image to a file"""
123 fname = tools.GetOutputFilename(self._filename)
124 with open(fname, 'wb') as fd:
125 self.BuildSection(fd, 0)
128 """Write a map of the image to a .map file
131 Filename of map file written
133 filename = '%s.map' % self.image_name
134 fname = tools.GetOutputFilename(filename)
135 with open(fname, 'w') as fd:
136 print('%8s %8s %8s %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
138 section.Entry_section.WriteMap(self, fd, 0)
141 def BuildEntryList(self):
142 """List the files in an image
145 List of entry.EntryInfo objects describing all entries in the image
148 self.ListEntries(entries, 0)