ARM: imx6q_logic: Fix MMC2 booting
[oweals/u-boot.git] / tools / binman / etype / image_header.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 an image header which points to the FDT map
6
7 This creates an 8-byte entry with a magic number and the offset of the FDT map
8 (which is another entry in the image), relative to the start or end of the
9 image.
10 """
11
12 import struct
13
14 from entry import Entry
15 import fdt_util
16
17 IMAGE_HEADER_MAGIC = b'BinM'
18 IMAGE_HEADER_LEN   = 8
19
20 def LocateHeaderOffset(data):
21     """Search an image for an image header
22
23     Args:
24         data: Data to search
25
26     Returns:
27         Offset of image header in the image, or None if not found
28     """
29     hdr_pos = data.find(IMAGE_HEADER_MAGIC)
30     if hdr_pos != -1:
31         size = len(data)
32         hdr = data[hdr_pos:hdr_pos + IMAGE_HEADER_LEN]
33         if len(hdr) == IMAGE_HEADER_LEN:
34             offset = struct.unpack('<I', hdr[4:])[0]
35             if hdr_pos == len(data) - IMAGE_HEADER_LEN:
36                 pos = size + offset - (1 << 32)
37             else:
38                 pos = offset
39             return pos
40     return None
41
42 class Entry_image_header(Entry):
43     """An entry which contains a pointer to the FDT map
44
45     Properties / Entry arguments:
46         location: Location of header ("start" or "end" of image). This is
47             optional. If omitted then the entry must have an offset property.
48
49     This adds an 8-byte entry to the start or end of the image, pointing to the
50     location of the FDT map. The format is a magic number followed by an offset
51     from the start or end of the image, in twos-compliment format.
52
53     This entry must be in the top-level part of the image.
54
55     NOTE: If the location is at the start/end, you will probably need to specify
56     sort-by-offset for the image, unless you actually put the image header
57     first/last in the entry list.
58     """
59     def __init__(self, section, etype, node):
60         Entry.__init__(self, section, etype, node)
61         self.location = fdt_util.GetString(self._node, 'location')
62
63     def _GetHeader(self):
64         image_pos = self.GetSiblingImagePos('fdtmap')
65         if image_pos == False:
66             self.Raise("'image_header' section must have an 'fdtmap' sibling")
67         elif image_pos is None:
68             # This will be available when called from ProcessContents(), but not
69             # when called from ObtainContents()
70             offset = 0xffffffff
71         else:
72             image_size = self.section.GetImageSize() or 0
73             base = (0 if self.location != 'end' else image_size)
74             offset = (image_pos - base) & 0xffffffff
75         data = IMAGE_HEADER_MAGIC + struct.pack('<I', offset)
76         return data
77
78     def ObtainContents(self):
79         """Obtain a placeholder for the header contents"""
80         self.SetContents(self._GetHeader())
81         return True
82
83     def Pack(self, offset):
84         """Special pack method to set the offset to start/end of image"""
85         if not self.offset:
86             if self.location not in ['start', 'end']:
87                 self.Raise("Invalid location '%s', expected 'start' or 'end'" %
88                            self.location)
89             order = self.GetSiblingOrder()
90             if self.location != order and not self.section.GetSort():
91                 self.Raise("Invalid sibling order '%s' for image-header: Must be at '%s' to match location" %
92                            (order, self.location))
93             if self.location != 'end':
94                 offset = 0
95             else:
96                 image_size = self.section.GetImageSize()
97                 if image_size is None:
98                     # We don't know the image, but this must be the last entry,
99                     # so we can assume it goes
100                     offset = offset
101                 else:
102                     offset = image_size - IMAGE_HEADER_LEN
103         return Entry.Pack(self, offset)
104
105     def ProcessContents(self):
106         """Write an updated version of the FDT map to this entry
107
108         This is necessary since image_pos is not available when ObtainContents()
109         is called, since by then the entries have not been packed in the image.
110         """
111         return self.ProcessContentsUpdate(self._GetHeader())