blob: 487290b6c4e840d17fef4ba7aa78114d64d4781c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass2574ef62016-11-25 20:15:51 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass2574ef62016-11-25 20:15:51 -07005# Class for an image, the output of binman
6#
7
Simon Glass4ca8e042017-11-13 18:55:01 -07008from __future__ import print_function
9
Simon Glass2574ef62016-11-25 20:15:51 -070010from collections import OrderedDict
11from operator import attrgetter
Simon Glass4ca8e042017-11-13 18:55:01 -070012import re
13import sys
Simon Glass2574ef62016-11-25 20:15:51 -070014
Simon Glass39dd2152019-07-08 14:25:47 -060015from entry import Entry
Simon Glassb8424fa2019-07-08 14:25:46 -060016from etype import fdtmap
17from etype import image_header
Simon Glass39dd2152019-07-08 14:25:47 -060018from etype import section
Simon Glassb8424fa2019-07-08 14:25:46 -060019import fdt
Simon Glass2574ef62016-11-25 20:15:51 -070020import fdt_util
21import tools
22
Simon Glass39dd2152019-07-08 14:25:47 -060023class Image(section.Entry_section):
Simon Glass2574ef62016-11-25 20:15:51 -070024 """A Image, representing an output from binman
25
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.
28
29 This class implements the various operations needed for images.
30
Simon Glass39dd2152019-07-08 14:25:47 -060031 Attributes:
32 filename: Output filename for image
Simon Glass1e324002018-06-01 09:38:19 -060033
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.
Simon Glass2574ef62016-11-25 20:15:51 -070038 """
Simon Glass4ca8e042017-11-13 18:55:01 -070039 def __init__(self, name, node, test=False):
Simon Glass39dd2152019-07-08 14:25:47 -060040 self.image = self
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
45 if not test:
46 filename = fdt_util.GetString(self._node, 'filename')
47 if filename:
48 self._filename = filename
Simon Glass2574ef62016-11-25 20:15:51 -070049
Simon Glassb8424fa2019-07-08 14:25:46 -060050 @classmethod
51 def FromFile(cls, fname):
52 """Convert an image file into an Image for use in binman
53
54 Args:
55 fname: Filename of image file to read
56
57 Returns:
58 Image object on success
59
60 Raises:
61 ValueError if something goes wrong
62 """
63 data = tools.ReadFile(fname)
64 size = len(data)
65
66 # First look for an image header
67 pos = image_header.LocateHeaderOffset(data)
68 if pos is None:
69 # Look for the FDT map
70 pos = fdtmap.LocateFdtmap(data)
71 if pos is None:
72 raise ValueError('Cannot find FDT map in image')
73
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:])
80 dtb.Scan()
81
82 # Return an Image with the associated nodes
83 return Image('image', dtb.GetRoot())
84
Simon Glasse61b6f62019-07-08 14:25:37 -060085 def Raise(self, msg):
86 """Convenience function to raise an error referencing an image"""
87 raise ValueError("Image '%s': %s" % (self._node.path, msg))
88
Simon Glass2574ef62016-11-25 20:15:51 -070089 def PackEntries(self):
90 """Pack all entries into the image"""
Simon Glass39dd2152019-07-08 14:25:47 -060091 section.Entry_section.Pack(self, 0)
Simon Glasse22f8fa2018-07-06 10:27:41 -060092
Simon Glass9dcc8612018-08-01 15:22:42 -060093 def SetImagePos(self):
Simon Glass39dd2152019-07-08 14:25:47 -060094 # This first section in the image so it starts at 0
95 section.Entry_section.SetImagePos(self, 0)
Simon Glass9dcc8612018-08-01 15:22:42 -060096
Simon Glass2574ef62016-11-25 20:15:51 -070097 def ProcessEntryContents(self):
98 """Call the ProcessContents() method for each entry
99
100 This is intended to adjust the contents as needed by the entry type.
Simon Glassec849852019-07-08 14:25:35 -0600101
102 Returns:
103 True if the new data size is OK, False if expansion is needed
Simon Glass2574ef62016-11-25 20:15:51 -0700104 """
Simon Glass39dd2152019-07-08 14:25:47 -0600105 sizes_ok = True
106 for entry in self._entries.values():
107 if not entry.ProcessContents():
108 sizes_ok = False
109 print("Entry '%s' size change" % self._node.path)
110 return sizes_ok
Simon Glass2574ef62016-11-25 20:15:51 -0700111
Simon Glass4ca8e042017-11-13 18:55:01 -0700112 def WriteSymbols(self):
113 """Write symbol values into binary files for access at run time"""
Simon Glass39dd2152019-07-08 14:25:47 -0600114 section.Entry_section.WriteSymbols(self, self)
115
116 def BuildSection(self, fd, base_offset):
117 """Write the section to a file"""
118 fd.seek(base_offset)
119 fd.write(self.GetData())
Simon Glass4ca8e042017-11-13 18:55:01 -0700120
Simon Glass2574ef62016-11-25 20:15:51 -0700121 def BuildImage(self):
122 """Write the image to a file"""
123 fname = tools.GetOutputFilename(self._filename)
124 with open(fname, 'wb') as fd:
Simon Glass39dd2152019-07-08 14:25:47 -0600125 self.BuildSection(fd, 0)
Simon Glass30732662018-06-01 09:38:20 -0600126
127 def WriteMap(self):
Simon Glasscd817d52018-09-14 04:57:36 -0600128 """Write a map of the image to a .map file
129
130 Returns:
131 Filename of map file written
132 """
Simon Glass39dd2152019-07-08 14:25:47 -0600133 filename = '%s.map' % self.image_name
Simon Glass30732662018-06-01 09:38:20 -0600134 fname = tools.GetOutputFilename(filename)
135 with open(fname, 'w') as fd:
Simon Glass7eca7922018-07-17 13:25:49 -0600136 print('%8s %8s %8s %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
137 file=fd)
Simon Glass39dd2152019-07-08 14:25:47 -0600138 section.Entry_section.WriteMap(self, fd, 0)
Simon Glasscd817d52018-09-14 04:57:36 -0600139 return fname
Simon Glass6b156f82019-07-08 14:25:43 -0600140
141 def BuildEntryList(self):
142 """List the files in an image
143
144 Returns:
145 List of entry.EntryInfo objects describing all entries in the image
146 """
147 entries = []
Simon Glass39dd2152019-07-08 14:25:47 -0600148 self.ListEntries(entries, 0)
Simon Glass6b156f82019-07-08 14:25:43 -0600149 return entries