Skip to content
Snippets Groups Projects
Commit dcb33d0a authored by Soumen Ghosh's avatar Soumen Ghosh
Browse files

lrdp-v2:read DCC from KMISC section for minidump

        As DCC is not going to be enabled on secure device,
        SDI would dump required registers in standard dcc dumping format.
        So extend ramparser’s DCC parsing support for <address><value> format.
        The KMISC section would contain all registers address value pair as mentioned below.
        Parse the data and generate the “dcc_captured_data.xml” and it should be same as actual dcc dump parsed xml.

Change-Id: Ib042ebc6895f0594f5784600174087a979e8709f
parent 561974c9
No related branches found
No related tags found
No related merge requests found
# Copyright (c) 2015-2017, 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 datetime
import logging
import logging.handlers
import os
import struct
import sys
from optparse import OptionParser
count = 0
address = []
data = []
def log_init(name, path, filename):
# Set up logger
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
# Add the log message handler to the logger
if filename is not None:
handler = logging.FileHandler(path + '/' + filename, mode='w')
else:
handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)
return logger
def read_data(data_pt):
nr = count
flag = 1
while nr > 0:
word = data_pt.read(4)
if len(word) != 4:
break
val = struct.unpack('<L', word)[0]
if flag % 2 != 0:
address.append(val)
else:
data.append(val)
flag = flag + 1
nr = nr - 1
return nr
def read_config(config_pt):
while True:
word = config_pt.read(4)
if len(word) != 4:
break
val = struct.unpack('<L', word)[0]
if val == 0:
break
return val
def dump_regs_json(options):
log.info("Dumping regs in JSON format in \'{0}\' file.".format(options.outfile))
parsed_data.info("{")
parsed_data.info("\t\"version\": 1,")
parsed_data.info("\t\"timestamp\": \"{0}\",".format(datetime.date.today().strftime('%m/%d/%y')))
parsed_data.info("\t\"generator\": \"Linux DCC Parser\",")
parsed_data.info("\t\"chip\": {")
parsed_data.info("\t\t\"name\": \"{0}\",".format(options.chipname))
parsed_data.info("\t\t\"version\": \"{0}\"".format(options.chipversion))
parsed_data.info("\t},")
parsed_data.info("\t\"registers\": [")
for addr, val in zip(address, data):
parsed_data.info("\t\t{{ \"address\": \"0x{0:08x}\", \"value\": \"0x{1:08x}\" }},".format(addr, val))
parsed_data.info("\t]")
parsed_data.info("}")
return
def dump_regs_xml(options):
print "dumping xml file"
log.info("Dumping regs in XML format in \'{0}\' file.".format(options.outfile))
parsed_data.info("<?xml version=\"1.0\" encoding=\"utf-8\"?>")
parsed_data.info("<hwioDump version=\"1\"")
parsed_data.info("\t<timestamp>{0}</timestamp>".format(datetime.date.today().strftime('%m/%d/%y')))
parsed_data.info("\t<generator>Linux DCC Parser</generator>")
parsed_data.info("\t<chip name=\"{0}\" version=\"{1}\">".format(options.chipname, options.chipversion))
for addr, val in zip(address, data):
parsed_data.info("\t\t<register address=\"0x{0:08x}\" value=\"0x{1:08x}\" />".format(addr, val))
parsed_data.info("\t</chip>")
parsed_data.info("</hwioDump>")
return
def dump_regs(options):
if options.json is True:
dump_regs_json(options)
else:
dump_regs_xml(options)
if __name__ == '__main__':
usage = 'usage: %prog [options to print]. Run with --help for more details'
parser = OptionParser(usage)
parser.add_option('-s', '--sysreg-file', dest='sysregfile',
help='sram image path')
parser.add_option('-j', '--json', action='store_true',
help='output in JSON format')
parser.add_option('-o', '--out-dir', dest='outdir', help='output dir path')
parser.add_option('-f', '--output-file', dest='outfile',
help='output filename')
parser.add_option('-l', '--log-file', dest='logfile', help='Log filename')
parser.add_option('', '--chip-name', dest='chipname', help='chip name')
parser.add_option('', '--chip-version', dest='chipversion',
help='chip version')
(options, args) = parser.parse_args()
print "sysregs_parser_invoked"
args = ''
for arg in sys.argv:
args = args + arg + ' '
if options.outdir:
if not os.path.exists(options.outdir):
print ('!!! Out directory does not exist. Creating...')
try:
os.makedirs(options.outdir)
except:
print ("Failed to create %s. You probably don't have permissions there. Bailing." % options.outdir)
sys.exit(1)
else:
options.outdir = '.'
if options.json:
ext = '.json'
else:
ext = '.xml'
if options.outfile is None:
options.outfile = 'dcc_captured_data_minidump{0}'.format(ext)
log = log_init('LOG', options.outdir, options.logfile)
log.info("Data Capture and Compare(sysregs) parser.")
if options.sysregfile is None:
log.error("No SRAM image file given! Exiting...")
parser.print_usage()
sys.exit(1)
try:
sysreg_file = open(options.sysregfile, 'rb')
except:
log.error("could not open path {0}".format(options.sysregfile))
log.error("Do you have read permissions on the path?")
sys.exit(1)
count = 0
count = read_config(sysreg_file)
if count == 0:
log.error('No configuration found in sysdbg_regs!!')
sys.exit(1)
if read_data(sysreg_file):
log.error('Couldn\'t read complete data.')
else:
parsed_data = log_init('PARSED_DATA', options.outdir, options.outfile)
dump_regs(options)
sysreg_file.close()
sys.stderr.flush()
...@@ -29,6 +29,7 @@ from watchdog_v2 import TZRegDump_v2 ...@@ -29,6 +29,7 @@ from watchdog_v2 import TZRegDump_v2
from cachedumplib import lookup_cache_type from cachedumplib import lookup_cache_type
from tlbdumplib import lookup_tlb_type from tlbdumplib import lookup_tlb_type
from vsens import VsensData from vsens import VsensData
from sysregs import SysRegDump
MEMDUMPV2_MAGIC = 0x42445953 MEMDUMPV2_MAGIC = 0x42445953
MAX_NUM_ENTRIES = 0x150 MAX_NUM_ENTRIES = 0x150
...@@ -45,6 +46,7 @@ class client(object): ...@@ -45,6 +46,7 @@ class client(object):
MSM_DUMP_DATA_L3_CACHE = 0xD0 MSM_DUMP_DATA_L3_CACHE = 0xD0
MSM_DUMP_DATA_OCMEM = 0xE0 MSM_DUMP_DATA_OCMEM = 0xE0
MSM_DUMP_DATA_DBGUI_REG = 0xE5 MSM_DUMP_DATA_DBGUI_REG = 0xE5
MSM_DUMP_DATA_MISC = 0xE8
MSM_DUMP_DATA_VSENSE = 0xE9 MSM_DUMP_DATA_VSENSE = 0xE9
MSM_DUMP_DATA_TMC_ETF = 0xF0 MSM_DUMP_DATA_TMC_ETF = 0xF0
MSM_DUMP_DATA_TMC_REG = 0x100 MSM_DUMP_DATA_TMC_REG = 0x100
...@@ -78,6 +80,7 @@ client_types = [ ...@@ -78,6 +80,7 @@ client_types = [
('MSM_DUMP_DATA_TMC_REG', 'parse_qdss_common'), ('MSM_DUMP_DATA_TMC_REG', 'parse_qdss_common'),
('MSM_DUMP_DATA_L2_TLB', 'parse_l2_tlb'), ('MSM_DUMP_DATA_L2_TLB', 'parse_l2_tlb'),
('MSM_DUMP_DATA_LLC_CACHE', 'parse_system_cache_common'), ('MSM_DUMP_DATA_LLC_CACHE', 'parse_system_cache_common'),
('MSM_DUMP_DATA_MISC', 'parse_sysdbg_regs'),
] ]
qdss_tag_to_field_name = { qdss_tag_to_field_name = {
...@@ -101,7 +104,8 @@ minidump_dump_table_type = [ ...@@ -101,7 +104,8 @@ minidump_dump_table_type = [
('MSM_DUMP_DATA_DCC_REG', 'KDCC_REG'), ('MSM_DUMP_DATA_DCC_REG', 'KDCC_REG'),
('MSM_DUMP_DATA_DCC_SRAM', 'KDCC_SRAM'), ('MSM_DUMP_DATA_DCC_SRAM', 'KDCC_SRAM'),
('MSM_DUMP_DATA_TMC_ETF', 'KTMC_ETF'), ('MSM_DUMP_DATA_TMC_ETF', 'KTMC_ETF'),
('MSM_DUMP_DATA_TMC_REG', 'KTMC_REG') ('MSM_DUMP_DATA_TMC_REG', 'KTMC_REG'),
('MSM_DUMP_DATA_MISC', 'KMISC')
] ]
...@@ -205,6 +209,19 @@ class DebugImage_v2(): ...@@ -205,6 +209,19 @@ class DebugImage_v2():
ram_dump.dcc = True ram_dump.dcc = True
return return
def parse_sysdbg_regs(self, version, start, end, client_id, ram_dump):
client_name = self.dump_data_id_lookup_table[client_id]
print_out_str(
'Parsing {0} context start {1:x} end {2:x}'.format(client_name, start, end))
sysregs = SysRegDump(start, end)
if sysregs.dump_sysreg_img(ram_dump) is False:
print_out_str('!!! Could not dump sysdbg_regs')
else:
ram_dump.sysreg = True
return
def parse_vsens(self, version, start, end, client_id, ram_dump): def parse_vsens(self, version, start, end, client_id, ram_dump):
client_name = self.dump_data_id_lookup_table[client_id] client_name = self.dump_data_id_lookup_table[client_id]
...@@ -470,6 +487,28 @@ class DebugImage_v2(): ...@@ -470,6 +487,28 @@ class DebugImage_v2():
print_out_str('--------') print_out_str('--------')
print_out_str(p.communicate()[0]) print_out_str(p.communicate()[0])
def parse_sysreg(self,ram_dump):
out_dir = ram_dump.outdir
sysreg_parser_path_minidump = os.path.join(os.path.dirname(__file__), '..', 'dcc_parser',
'sysregs_parser_minidump.py')
if sysreg_parser_path_minidump is None:
print_out_str("!!! Incorrect path for SYSREG specified.")
return
if not os.path.exists(sysreg_parser_path_minidump):
print_out_str("!!! sysreg_parser_path_minidump {0} does not exist! "
"Check your settings!"
.format(sysreg_parser_path_minidump))
return
if os.path.getsize(os.path.join(out_dir, 'sysdbg_regs.bin')) > 0:
sysdbg_file = os.path.join(out_dir, 'sysdbg_regs.bin')
else:
return
p = subprocess.Popen([sys.executable, sysreg_parser_path_minidump, '-s', sysdbg_file, '--out-dir', out_dir],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print_out_str('--------')
print_out_str(p.communicate()[0])
def sorted_dump_data_clients(self, ram_dump, table, table_num_entries): def sorted_dump_data_clients(self, ram_dump, table, table_num_entries):
""" Returns a sorted list of (client_name, func, client_address) where """ Returns a sorted list of (client_name, func, client_address) where
...@@ -768,6 +807,8 @@ class DebugImage_v2(): ...@@ -768,6 +807,8 @@ class DebugImage_v2():
client_end, client_id, ram_dump) client_end, client_id, ram_dump)
if ram_dump.dcc: if ram_dump.dcc:
self.parse_dcc(ram_dump) self.parse_dcc(ram_dump)
if ram_dump.sysreg:
self.parse_sysreg(ram_dump)
self.qdss.dump_standard(ram_dump) self.qdss.dump_standard(ram_dump)
if not ram_dump.skip_qdss_bin: if not ram_dump.skip_qdss_bin:
self.qdss.save_etf_bin(ram_dump) self.qdss.save_etf_bin(ram_dump)
......
...@@ -528,6 +528,7 @@ class RamDump(): ...@@ -528,6 +528,7 @@ class RamDump():
self.qtf = options.qtf self.qtf = options.qtf
self.skip_qdss_bin = options.skip_qdss_bin self.skip_qdss_bin = options.skip_qdss_bin
self.dcc = False self.dcc = False
self.sysreg = False
self.t32_host_system = options.t32_host_system or None self.t32_host_system = options.t32_host_system or None
self.ipc_log_test = options.ipc_test self.ipc_log_test = options.ipc_test
self.ipc_log_skip = options.ipc_skip self.ipc_log_skip = options.ipc_skip
......
# Copyright (c) 2015-2017, 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 struct
import os
from print_out import print_out_str
from ramparse import VERSION
class SysRegDump():
def __init__(self, start, end):
self.start_addr = start
self.end_addr = end
def dump_sysreg_img(self,ram_dump):
if self.start_addr >= self.end_addr:
return False
rsz = self.end_addr - self.start_addr
sysregfile = ram_dump.open_file('sysdbg_regs.bin')
for i in range(0, rsz):
val = ram_dump.read_byte(self.start_addr + i, False)
sysregfile.write(struct.pack('<B', val))
sysregfile.close()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment