1# SPDX-License-Identifier: GPL-2.0+
2# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
5# Entry-type module for 'u-boot'
6#
7
8import struct
9
10from entry import Entry
11from blob import Entry_blob
12
13FD_SIGNATURE   = struct.pack('<L', 0x0ff0a55a)
14MAX_REGIONS    = 5
15
16(REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
17        REGION_PDATA) = range(5)
18
19class Region:
20    def __init__(self, data, frba, region_num):
21        pos = frba + region_num * 4
22        val = struct.unpack('<L', data[pos:pos + 4])[0]
23        self.base = (val & 0xfff) << 12
24        self.limit = ((val & 0x0fff0000) >> 4) | 0xfff
25        self.size = self.limit - self.base + 1
26
27class Entry_intel_descriptor(Entry_blob):
28    """Intel flash descriptor block (4KB)
29
30    This is placed at the start of flash and provides information about
31    the SPI flash regions. In particular it provides the base address and
32    size of the ME region, allowing us to place the ME binary in the right
33    place.
34    """
35    def __init__(self, section, etype, node):
36        Entry_blob.__init__(self, section, etype, node)
37        self._regions = []
38
39    def GetPositions(self):
40        pos = self.data.find(FD_SIGNATURE)
41        if pos == -1:
42            self.Raise('Cannot find FD signature')
43        flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
44                                                    self.data[pos:pos + 16])
45        frba = ((flmap0 >> 16) & 0xff) << 4
46        for i in range(MAX_REGIONS):
47            self._regions.append(Region(self.data, frba, i))
48
49        # Set the offset for ME only, for now, since the others are not used
50        return {'intel-me': [self._regions[REGION_ME].base,
51                             self._regions[REGION_ME].size]}
52