#
#  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
#
#  SPDX-License-Identifier: BSD-2-Clause-Patent
#

from arm_ds.debugger_v1 import DebugException

import struct

import edk2_debugger
import firmware_volume

class DebugInfoTable:
    CONST_DEBUG_INFO_TABLE_GUID = ( 0x49152E77L, 0x47641ADAL, 0xFE7AA2B7L, 0x8B5ED9FEL)

    DebugInfos = []

    def __init__(self, ec, debug_info_table_header_offset):
        self.ec = ec
        self.base = debug_info_table_header_offset

    def get_debug_info(self):
        # Get the information from EFI_DEBUG_IMAGE_INFO_TABLE_HEADER
        count = self.ec.getMemoryService().readMemory32(self.base + 0x4)
        if edk2_debugger.is_aarch64(self.ec):
            debug_info_table_base = self.ec.getMemoryService().readMemory64(self.base + 0x8)
        else:
            debug_info_table_base = self.ec.getMemoryService().readMemory32(self.base + 0x8)

        self.DebugInfos = []

        for i in range(0, count):
            # Get the address of the structure EFI_DEBUG_IMAGE_INFO
            if edk2_debugger.is_aarch64(self.ec):
                debug_info = self.ec.getMemoryService().readMemory64(debug_info_table_base + (i * 8))
            else:
                debug_info = self.ec.getMemoryService().readMemory32(debug_info_table_base + (i * 4))

            if debug_info:
                debug_info_type = self.ec.getMemoryService().readMemory32(debug_info)
                # Normal Debug Info Type
                if debug_info_type == 1:
                    if edk2_debugger.is_aarch64(self.ec):
                        # Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
                        loaded_image_protocol = self.ec.getMemoryService().readMemory64(debug_info + 0x8)

                        image_base = self.ec.getMemoryService().readMemory64(loaded_image_protocol + 0x40)
                        image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x48)
                    else:
                        # Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
                        loaded_image_protocol = self.ec.getMemoryService().readMemory32(debug_info + 0x4)

                        image_base = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x20)
                        image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x28)

                    self.DebugInfos.append((image_base,image_size))

    # Return (base, size)
    def load_symbols_at(self, addr, verbose = False):
        if self.DebugInfos == []:
            self.get_debug_info()

        found = False
        for debug_info in self.DebugInfos:
            if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
                if edk2_debugger.is_aarch64(self.ec):
                    section = firmware_volume.EfiSectionPE64(self.ec, debug_info[0])
                else:
                    section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])

                try:
                    edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
                except Exception, (ErrorClass, ErrorMessage):
                    if verbose:
                        print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)

                found = True
                return debug_info

        if found == False:
            raise Exception('DebugInfoTable','No symbol found at 0x%x' % addr)

    def load_all_symbols(self, verbose = False):
        if self.DebugInfos == []:
            self.get_debug_info()

        for debug_info in self.DebugInfos:
            if edk2_debugger.is_aarch64(self.ec):
                section = firmware_volume.EfiSectionPE64(self.ec, debug_info[0])
            else:
                section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])

            try:
                edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase(), verbose)
            except Exception, (ErrorClass, ErrorMessage):
                if verbose:
                    print "Error while loading a symbol file (%s: %s)" % (ErrorClass, ErrorMessage)

    def dump(self):
        self.get_debug_info()
        for debug_info in self.DebugInfos:
            base_pe32 = debug_info[0]
            if edk2_debugger.is_aarch64(self.ec):
                section = firmware_volume.EfiSectionPE64(self.ec, base_pe32)
            else:
                section = firmware_volume.EfiSectionPE32(self.ec, base_pe32)
            print section.get_debug_filepath()

class SystemTable:
    CONST_ST_SIGNATURE = ('I','B','I',' ','S','Y','S','T')

    def __init__(self, ec, membase, memsize):
        self.membase = membase
        self.memsize = memsize
        self.ec = ec

        found = False

        # Start from the top of the memory
        offset = self.membase + self.memsize
        # Align to highest 4MB boundary
        offset = offset & ~0x3FFFFF
        # We should not have a System Table at the top of the System Memory
        offset = offset - 0x400000

        # Start at top and look on 4MB boundaries for system table ptr structure
        while offset > self.membase:
            try:
                signature = struct.unpack("cccccccc", self.ec.getMemoryService().read(str(offset), 8, 32))
            except DebugException:
                raise Exception('SystemTable','Fail to access System Memory. Ensure all the memory in the region [0x%x;0x%X] is accessible.' % (membase,membase+memsize))
            if signature == SystemTable.CONST_ST_SIGNATURE:
                found = True
                if edk2_debugger.is_aarch64(self.ec):
                    self.system_table_base = self.ec.getMemoryService().readMemory64(offset + 0x8)
                else:
                    self.system_table_base = self.ec.getMemoryService().readMemory32(offset + 0x8)
                break
            offset = offset - 0x400000

        if not found:
            raise Exception('SystemTable','System Table not found in System Memory [0x%x;0x%X]' % (membase,membase+memsize))

    def get_configuration_table(self, conf_table_guid):
        if edk2_debugger.is_aarch64(self.ec):
            # Number of configuration Table entry
            conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x68)

            # Get location of the Configuration Table entries
            conf_table_offset = self.ec.getMemoryService().readMemory64(self.system_table_base + 0x70)
        else:
            # Number of configuration Table entry
            conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x40)

            # Get location of the Configuration Table entries
            conf_table_offset = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x44)

        for i in range(0, conf_table_entry_count):
            if edk2_debugger.is_aarch64(self.ec):
                offset = conf_table_offset + (i * 0x18)
            else:
                offset = conf_table_offset + (i * 0x14)
            guid = struct.unpack("<IIII", self.ec.getMemoryService().read(str(offset), 16, 32))
            if guid == conf_table_guid:
                if edk2_debugger.is_aarch64(self.ec):
                    return self.ec.getMemoryService().readMemory64(offset + 0x10)
                else:
                    return self.ec.getMemoryService().readMemory32(offset + 0x10)

        raise Exception('SystemTable','Configuration Table not found')
