1#
2# Copyright (c) 2023-2024, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6
7from re import match, search
8from typing import TextIO
9
10
11class TfaMapParser:
12    """A class representing a map file built for TF-A.
13
14    Provides a basic interface for reading the symbol table. The constructor
15    accepts a file-like object with the contents a Map file. Only GNU map files
16    are supported at this stage.
17    """
18
19    def __init__(self, map_file: TextIO):
20        self._symbols = self.read_symbols(map_file)
21
22    @property
23    def symbols(self):
24        return self._symbols.items()
25
26    @staticmethod
27    def read_symbols(file: TextIO, pattern: str = None) -> dict:
28        pattern = r"\b(0x\w*)\s*(\w*)\s=" if not pattern else pattern
29        symbols = {}
30
31        for line in file.readlines():
32            match = search(pattern, line)
33
34            if match is not None:
35                value, name = match.groups()
36                symbols[name] = int(value, 16)
37
38        return symbols
39
40    def get_memory_layout(self) -> dict:
41        """Get the total memory consumed by this module from the memory
42        configuration.
43            {"rom": {"start": 0x0, "end": 0xFF, "length": ... }
44        """
45        assert len(self._symbols), "Symbol table is empty!"
46        expr = r".*(.?R.M)_REGION.*(START|END|LENGTH)"
47        memory_layout = {}
48
49        region_symbols = filter(lambda s: match(expr, s), self._symbols)
50
51        for symbol in region_symbols:
52            region, _, attr = tuple(symbol.lower().strip("__").split("_"))
53            if region not in memory_layout:
54                memory_layout[region] = {}
55
56            memory_layout[region][attr] = self._symbols[symbol]
57
58            if "start" and "length" and "end" in memory_layout[region]:
59                memory_layout[region]["limit"] = (
60                    memory_layout[region]["start"]
61                    + memory_layout[region]["length"]
62                )
63                memory_layout[region]["free"] = (
64                    memory_layout[region]["limit"]
65                    - memory_layout[region]["end"]
66                )
67                memory_layout[region]["total"] = memory_layout[region][
68                    "length"
69                ]
70                memory_layout[region]["size"] = (
71                    memory_layout[region]["end"]
72                    - memory_layout[region]["start"]
73                )
74
75        return memory_layout
76