Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | # SPDX-License-Identifier: GPL-2.0+ |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 2 | # Copyright (c) 2016 Google, Inc |
| 3 | # Written by Simon Glass <sjg@chromium.org> |
| 4 | # |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 5 | # Class for an image, the output of binman |
| 6 | # |
| 7 | |
Simon Glass | 4ca8e04 | 2017-11-13 18:55:01 -0700 | [diff] [blame] | 8 | from __future__ import print_function |
| 9 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 10 | from collections import OrderedDict |
| 11 | from operator import attrgetter |
Simon Glass | 4ca8e04 | 2017-11-13 18:55:01 -0700 | [diff] [blame] | 12 | import re |
| 13 | import sys |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 14 | |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 15 | from entry import Entry |
Simon Glass | b8424fa | 2019-07-08 14:25:46 -0600 | [diff] [blame] | 16 | from etype import fdtmap |
| 17 | from etype import image_header |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 18 | from etype import section |
Simon Glass | b8424fa | 2019-07-08 14:25:46 -0600 | [diff] [blame] | 19 | import fdt |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 20 | import fdt_util |
| 21 | import tools |
| 22 | |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 23 | class Image(section.Entry_section): |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 24 | """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 Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 31 | Attributes: |
| 32 | filename: Output filename for image |
Simon Glass | 1e32400 | 2018-06-01 09:38:19 -0600 | [diff] [blame] | 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. |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 38 | """ |
Simon Glass | 4ca8e04 | 2017-11-13 18:55:01 -0700 | [diff] [blame] | 39 | def __init__(self, name, node, test=False): |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 40 | 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 Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 49 | |
Simon Glass | b8424fa | 2019-07-08 14:25:46 -0600 | [diff] [blame] | 50 | @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 Glass | e61b6f6 | 2019-07-08 14:25:37 -0600 | [diff] [blame] | 85 | 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 Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 89 | def PackEntries(self): |
| 90 | """Pack all entries into the image""" |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 91 | section.Entry_section.Pack(self, 0) |
Simon Glass | e22f8fa | 2018-07-06 10:27:41 -0600 | [diff] [blame] | 92 | |
Simon Glass | 9dcc861 | 2018-08-01 15:22:42 -0600 | [diff] [blame] | 93 | def SetImagePos(self): |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 94 | # This first section in the image so it starts at 0 |
| 95 | section.Entry_section.SetImagePos(self, 0) |
Simon Glass | 9dcc861 | 2018-08-01 15:22:42 -0600 | [diff] [blame] | 96 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 97 | 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 Glass | ec84985 | 2019-07-08 14:25:35 -0600 | [diff] [blame] | 101 | |
| 102 | Returns: |
| 103 | True if the new data size is OK, False if expansion is needed |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 104 | """ |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 105 | 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 Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 111 | |
Simon Glass | 4ca8e04 | 2017-11-13 18:55:01 -0700 | [diff] [blame] | 112 | def WriteSymbols(self): |
| 113 | """Write symbol values into binary files for access at run time""" |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 114 | 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 Glass | 4ca8e04 | 2017-11-13 18:55:01 -0700 | [diff] [blame] | 120 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 121 | def BuildImage(self): |
| 122 | """Write the image to a file""" |
| 123 | fname = tools.GetOutputFilename(self._filename) |
| 124 | with open(fname, 'wb') as fd: |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 125 | self.BuildSection(fd, 0) |
Simon Glass | 3073266 | 2018-06-01 09:38:20 -0600 | [diff] [blame] | 126 | |
| 127 | def WriteMap(self): |
Simon Glass | cd817d5 | 2018-09-14 04:57:36 -0600 | [diff] [blame] | 128 | """Write a map of the image to a .map file |
| 129 | |
| 130 | Returns: |
| 131 | Filename of map file written |
| 132 | """ |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 133 | filename = '%s.map' % self.image_name |
Simon Glass | 3073266 | 2018-06-01 09:38:20 -0600 | [diff] [blame] | 134 | fname = tools.GetOutputFilename(filename) |
| 135 | with open(fname, 'w') as fd: |
Simon Glass | 7eca792 | 2018-07-17 13:25:49 -0600 | [diff] [blame] | 136 | print('%8s %8s %8s %s' % ('ImagePos', 'Offset', 'Size', 'Name'), |
| 137 | file=fd) |
Simon Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 138 | section.Entry_section.WriteMap(self, fd, 0) |
Simon Glass | cd817d5 | 2018-09-14 04:57:36 -0600 | [diff] [blame] | 139 | return fname |
Simon Glass | 6b156f8 | 2019-07-08 14:25:43 -0600 | [diff] [blame] | 140 | |
| 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 Glass | 39dd215 | 2019-07-08 14:25:47 -0600 | [diff] [blame^] | 148 | self.ListEntries(entries, 0) |
Simon Glass | 6b156f8 | 2019-07-08 14:25:43 -0600 | [diff] [blame] | 149 | return entries |