1#
2#  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
3#
4#  This program and the accompanying materials
5#  are licensed and made available under the terms and conditions of the BSD License
6#  which accompanies this distribution.  The full text of the license may be found at
7#  http://opensource.org/licenses/bsd-license.php
8#
9#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11#
12
13from arm_ds.debugger_v1 import DebugException
14
15import struct
16
17import edk2_debugger
18import firmware_volume
19
20class DebugInfoTable:
21    CONST_DEBUG_INFO_TABLE_GUID = ( 0x49152E77L, 0x47641ADAL, 0xFE7AA2B7L, 0x8B5ED9FEL)
22
23    DebugInfos = []
24
25    def __init__(self, ec, debug_info_table_header_offset):
26        self.ec = ec
27        self.base = debug_info_table_header_offset
28
29    def get_debug_info(self):
30        # Get the information from EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
31        count = self.ec.getMemoryService().readMemory32(self.base + 0x4)
32        if edk2_debugger.is_aarch64(self.ec):
33            debug_info_table_base = self.ec.getMemoryService().readMemory64(self.base + 0x8)
34        else:
35            debug_info_table_base = self.ec.getMemoryService().readMemory32(self.base + 0x8)
36
37        self.DebugInfos = []
38
39        for i in range(0, count):
40            # Get the address of the structure EFI_DEBUG_IMAGE_INFO
41            if edk2_debugger.is_aarch64(self.ec):
42                debug_info = self.ec.getMemoryService().readMemory64(debug_info_table_base + (i * 8))
43            else:
44                debug_info = self.ec.getMemoryService().readMemory32(debug_info_table_base + (i * 4))
45
46            if debug_info:
47                debug_info_type = self.ec.getMemoryService().readMemory32(debug_info)
48                # Normal Debug Info Type
49                if debug_info_type == 1:
50                    if edk2_debugger.is_aarch64(self.ec):
51                        # Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
52                        loaded_image_protocol = self.ec.getMemoryService().readMemory64(debug_info + 0x8)
53
54                        image_base = self.ec.getMemoryService().readMemory64(loaded_image_protocol + 0x40)
55                        image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x48)
56                    else:
57                        # Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
58                        loaded_image_protocol = self.ec.getMemoryService().readMemory32(debug_info + 0x4)
59
60                        image_base = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x20)
61                        image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x28)
62
63                    self.DebugInfos.append((image_base,image_size))
64
65    # Return (base, size)
66    def load_symbols_at(self, addr, verbose = False):
67        if self.DebugInfos == []:
68            self.get_debug_info()
69
70        found = False
71        for debug_info in self.DebugInfos:
72            if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
73                if edk2_debugger.is_aarch64(self.ec):
74                    section = firmware_volume.EfiSectionPE64(self.ec, debug_info[0])
75                else:
76                    section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])
77
78                try:
79                    edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
80                except Exception, (ErrorClass, ErrorMessage):
81                    if verbose:
82                        print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
83
84                found = True
85                return debug_info
86
87        if found == False:
88            raise Exception('DebugInfoTable','No symbol found at 0x%x' % addr)
89
90    def load_all_symbols(self, verbose = False):
91        if self.DebugInfos == []:
92            self.get_debug_info()
93
94        for debug_info in self.DebugInfos:
95            if edk2_debugger.is_aarch64(self.ec):
96                section = firmware_volume.EfiSectionPE64(self.ec, debug_info[0])
97            else:
98                section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])
99
100            try:
101                edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
102            except Exception, (ErrorClass, ErrorMessage):
103                if verbose:
104                    print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)
105
106    def dump(self):
107        self.get_debug_info()
108        for debug_info in self.DebugInfos:
109            base_pe32 = debug_info[0]
110            if edk2_debugger.is_aarch64(self.ec):
111                section = firmware_volume.EfiSectionPE64(self.ec, base_pe32)
112            else:
113                section = firmware_volume.EfiSectionPE32(self.ec, base_pe32)
114            print section.get_debug_filepath()
115
116class SystemTable:
117    CONST_ST_SIGNATURE = ('I','B','I',' ','S','Y','S','T')
118
119    def __init__(self, ec, membase, memsize):
120        self.membase = membase
121        self.memsize = memsize
122        self.ec = ec
123
124        found = False
125
126        # Start from the top of the memory
127        offset = self.membase + self.memsize
128        # Align to highest 4MB boundary
129        offset = offset & ~0x3FFFFF
130        # We should not have a System Table at the top of the System Memory
131        offset = offset - 0x400000
132
133        # Start at top and look on 4MB boundaries for system table ptr structure
134        while offset > self.membase:
135            try:
136                signature = struct.unpack("cccccccc", self.ec.getMemoryService().read(str(offset), 8, 32))
137            except DebugException:
138                raise Exception('SystemTable','Fail to access System Memory. Ensure all the memory in the region [0x%x;0x%X] is accessible.' % (membase,membase+memsize))
139            if signature == SystemTable.CONST_ST_SIGNATURE:
140                found = True
141                if edk2_debugger.is_aarch64(self.ec):
142                    self.system_table_base = self.ec.getMemoryService().readMemory64(offset + 0x8)
143                else:
144                    self.system_table_base = self.ec.getMemoryService().readMemory32(offset + 0x8)
145                break
146            offset = offset - 0x400000
147
148        if not found:
149            raise Exception('SystemTable','System Table not found in System Memory [0x%x;0x%X]' % (membase,membase+memsize))
150
151    def get_configuration_table(self, conf_table_guid):
152        if edk2_debugger.is_aarch64(self.ec):
153            # Number of configuration Table entry
154            conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x68)
155
156            # Get location of the Configuration Table entries
157            conf_table_offset = self.ec.getMemoryService().readMemory64(self.system_table_base + 0x70)
158        else:
159            # Number of configuration Table entry
160            conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x40)
161
162            # Get location of the Configuration Table entries
163            conf_table_offset = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x44)
164
165        for i in range(0, conf_table_entry_count):
166            if edk2_debugger.is_aarch64(self.ec):
167                offset = conf_table_offset + (i * 0x18)
168            else:
169                offset = conf_table_offset + (i * 0x14)
170            guid = struct.unpack("<IIII", self.ec.getMemoryService().read(str(offset), 16, 32))
171            if guid == conf_table_guid:
172                if edk2_debugger.is_aarch64(self.ec):
173                    return self.ec.getMemoryService().readMemory64(offset + 0x10)
174                else:
175                    return self.ec.getMemoryService().readMemory32(offset + 0x10)
176
177        raise Exception('SystemTable','Configuration Table not found')
178