diff --git a/linux-ramdump-parser-v2/README b/linux-ramdump-parser-v2/README index 2b9f5da8ca3be5cc0383ad2a97d717252f42469e..84993be6db794deadcb6770e0fd9595329fa77a7 100644 --- a/linux-ramdump-parser-v2/README +++ b/linux-ramdump-parser-v2/README @@ -91,6 +91,7 @@ nm_path - absolute path to the gdb tool for the ramdumps gdb64_path - absolute path to the 64-bit gdb tool for the ramdumps nm64_path - absolute path to the 64-bit nm tool for the ramdumps qtf_path - absolute path to qtf tool executable +scandump_parser_path - absolute path to scandump parser for the ramdumps Note that local_settings.py is just a python file so the file may take advantage of python features. diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py old mode 100644 new mode 100755 index 1bc53cc2f794203ccfc40113064cda97cb3cdd6d..92af3139f0f3bfc075cfe403e0808e1663c5b580 --- a/linux-ramdump-parser-v2/debug_image_v2.py +++ b/linux-ramdump-parser-v2/debug_image_v2.py @@ -19,6 +19,7 @@ import random import subprocess import sys import time +import local_settings from dcc import DccRegDump, DccSramDump from pmic import PmicRegDump @@ -50,10 +51,12 @@ class client(object): MSM_DUMP_DATA_LOG_BUF = 0x110 MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111 MSM_DUMP_DATA_L2_TLB = 0x120 + MSM_DUMP_DATA_SCANDUMP = 0xEB MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES # Client functions will be executed in top-to-bottom order client_types = [ + ('MSM_DUMP_DATA_SCANDUMP', 'parse_scandump'), ('MSM_DUMP_DATA_CPU_CTX', 'parse_cpu_ctx'), ('MSM_DUMP_DATA_L1_INST_TLB', 'parse_l1_inst_tlb'), ('MSM_DUMP_DATA_L1_DATA_TLB', 'parse_l1_data_tlb'), @@ -92,6 +95,34 @@ class DebugImage_v2(): else: self.event_call = 'struct ftrace_event_call' self.event_class = 'struct ftrace_event_class' + self.has_scan_dump = False + + def parse_scandump(self, version, start, end, client_id, ram_dump): + scandump_file_prefix = "scandump" + try: + scan_wrapper_path = local_settings.scandump_parser_path + except AttributeError: + print_out_str('Could not find scandump_parser_path . Please define scandump_parser_path in local_settings') + return + if client_id == client.MSM_DUMP_DATA_SCANDUMP: + self.has_scan_dump = True + output = os.path.join(ram_dump.outdir, scandump_file_prefix) + if os.path.isfile(os.path.join(ram_dump.outdir, "vv_msg_4_header.bin")): + input = os.path.join(ram_dump.outdir, "vv_msg_4_header.bin") + else: + print_out_str('File vv_msg_4_header.bin is expected to parse scandump') + return + print_out_str( + 'Parsing scandump context start {0:x} end {1:x} {2} {3}'.format(start, end, output, input)) + if ram_dump.arm64: + arch = "aarch64" + header_bin = ram_dump.open_file(input) + it = range(start, end) + for i in it: + val = ram_dump.read_byte(i, False) + header_bin.write(struct.pack("<B", val)) + header_bin.close() + subprocess.call('python {0} -d {1} -o {2} -f {3}'.format(scan_wrapper_path, input, output, arch)) def parse_cpu_ctx(self, version, start, end, client_id, ram_dump): core = client_id - client.MSM_DUMP_DATA_CPU_CTX @@ -99,7 +130,7 @@ class DebugImage_v2(): print_out_str( 'Parsing CPU{2} context start {0:x} end {1:x}'.format(start, end, core)) - regs = TZRegDump_v2() + regs = TZRegDump_v2(self.has_scan_dump) if regs.init_regs(version, start, end, core, ram_dump) is False: print_out_str('!!! Could not get registers from TZ dump') return @@ -562,7 +593,6 @@ class DebugImage_v2(): client_addr + dump_data_addr_offset, False) dump_data_len = ram_dump.read_dword( client_addr + dump_data_len_offset, False) - print_out_str('Parsing debug information for {0}. Version: {1} Magic: {2:x} Source: {3}'.format( client_name, dump_data_version, dump_data_magic, dump_data_name)) diff --git a/linux-ramdump-parser-v2/scandump_reader.py b/linux-ramdump-parser-v2/scandump_reader.py new file mode 100755 index 0000000000000000000000000000000000000000..eb2e3da87882305457240bbf95cfc20b213cad39 --- /dev/null +++ b/linux-ramdump-parser-v2/scandump_reader.py @@ -0,0 +1,53 @@ +# Copyright (c) 2016, The Linux Foundation. All rights reserved. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 and +# only version 2 as published by the Free Software Foundation. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + + +import re +import os +from print_out import print_out_str + + +class Scandump_v2(): + + def __init__(self, core, ramdump, version): + self.core = core + self.regs = {} + self.version = version + self.ramdump = ramdump + self.init_missing_regs() + + def init_missing_regs(self): + self.regs['currentEL'] = 0 + self.regs['spsr_el1'] = 0 + self.regs['spsr_el2'] = 0 + self.regs['spsr_el3'] = 0 + self.regs['cpu_state_0'] = 0 + self.regs['cpu_state_1'] = 0 + self.regs['cpu_state_3'] = 0 + self.regs['cpu_state_4'] = 0 + self.regs['cpu_state_5'] = 0 + + + def prepare_dict(self): + input_file = "scandump" + input_file_name = "{0}_core{1}.cmm".format(input_file, (self.core - 4)) + output = os.path.join(self.ramdump.outdir, input_file_name) + fd = open(output, "r") + for line in fd: + matchObj = re.match('^REGISTER.SET ([xse].*[0-9]+)\s(0x[0-9a-f]{0,})', line, re.M | re.I) + if matchObj: + regVal = matchObj.group(2) + if regVal == "0x": + regVal = "0x0000000000000000" + self.regs[(matchObj.group(1)).lower()] = int(regVal, 16) + else: + continue + return self.regs diff --git a/linux-ramdump-parser-v2/watchdog_v2.py b/linux-ramdump-parser-v2/watchdog_v2.py old mode 100644 new mode 100755 index 8801d352b3537907359203cf980acac58197ddf1..dba99d615f277bc521011a4f76643fce2c763767 --- a/linux-ramdump-parser-v2/watchdog_v2.py +++ b/linux-ramdump-parser-v2/watchdog_v2.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -11,6 +11,8 @@ import struct import re + +from scandump_reader import Scandump_v2 from print_out import print_out_str from bitops import is_set @@ -693,7 +695,7 @@ class TZCpuCtx_v2(): class TZRegDump_v2(): - def __init__(self): + def __init__(self, has_scan_dump): self.core_regs = None self.sec_regs = None self.neon_regs = {} @@ -703,6 +705,7 @@ class TZRegDump_v2(): self.core = 0 self.status = [] self.neon_fields = [] + self.has_scan_dump = has_scan_dump def dump_all_regs(self, ram_dump): coren_regs = ram_dump.open_file('core{0}_regs.cmm'.format(self.core)) @@ -815,8 +818,21 @@ class TZRegDump_v2(): self.start_addr += struct.calcsize( sysdbg_cpu32_ctxt_regs_type[self.version]) + if self.has_scan_dump: + if core > 3: + self.scan_data = Scandump_v2(self.core, ram_dump, self.version) + self.scan_regs = self.scan_data.prepare_dict() + else: + print_out_str("No Scan dump data to be processed...") + self.core_regs = TZCpuCtx_v2(self.version, sc_regs, self.neon_regs, ram_dump) + + if core > 3: + if self.has_scan_dump: + self.scan_regs['pc'] = self.core_regs.regs['pc'] + self.core_regs.regs = self.scan_regs + self.sec_regs = TZCpuCtx_v2(self.version, sc_secure, self.neon_regs, ram_dump) return True