blob: 13c75583f7880ed21fd5b60ccfee3782d3336dcf [file] [log] [blame]
import argparse
import os
from subprocess import Popen, PIPE
version = "1.2"
#Fixed Pattern
EDBGINFO = "EDBGINFO\x05\x00\x00\x00"
SKIPPATTERN = "\x53\x4B\x49\x50"
MRDUMPBI = "MRDUMPBI"
#Start/End Guard Eable
haveStartGuard = False
haveEndGuard = False
#Default AP vmlinux path (for auto find function)
apSymbolPathWIN = "\\\\mtksfs00\\srv_colgin_ci\\image\\SanityLoad\\"
apSymbolPathLINUX = "/proj/srv_colgin_ci/image/SanityLoad/"
#Default value (would be overwitten)
remappingBank4 = [[0x40000000, 0x8e000000], [0x46000000, 0x84000000]]
remappingBank0 = [0x00000000, 0xae000000]
DRAMOffset = 0x40000000
fileOffset = 0x00004000
def ParsingArgument() :
parser = argparse.ArgumentParser()
parser.add_argument("-i", type=str, dest="core_dump", required=True, help="Input full ram dump path")
parser.add_argument("-o", type=str, dest="output", required=True, help="Output memory dump file path")
parser.add_argument("-p", "--use_mrdump_tool",type=str, dest="use_mrdump_tool", default="No", help="Set this flag \"True\" to use merdump tool to extract SYS_COREDUMP info for supporting lagacy version")
parser.add_argument("-e", "--elf", type=str, default='', dest="vmlinux", help="Input vmlinux (ELF) path")
parser.add_argument("-t", "--mrdump-tool", type=str, default='mrdump-gdb', dest="dump_tool_path",help="MRDUMP Tool path (ex. dump-tools-1.00/mrdump-gdb)\
https://wiki.mediatek.inc/pages/viewpage.action?pageId=58229130")
return (parser.parse_args().core_dump, parser.parse_args().output, parser.parse_args().use_mrdump_tool, parser.parse_args().vmlinux, parser.parse_args().dump_tool_path)
def ConvertMD2APAddress(MDAddress) :
if MDAddress[-1] >> 4 == 0 or MDAddress[-1] >> 4 == 2 or MDAddress[-1] >> 4 == 3 or MDAddress[-1] >> 4 == 6 or MDAddress[-1] >> 4 == 9 :
bank = 0
elif MDAddress[-1] >> 4 == 1 or MDAddress[-1] >> 4 == 7 :
bank = 1
elif MDAddress[-1] >> 4 == 4 :
bank = 4
else :
bank = -1
intMDAddress = int.from_bytes(MDAddress[0:3], "little")
if bank == 0 :
APAddress = intMDAddress - remappingBank0[0] + remappingBank0[1]
elif bank == 1 :
APAddress = intMDAddress - remappingBank0[0] + remappingBank0[1] + 0x02000000
elif bank == 4 :
if MDAddress[-1] & 15 < 6 :
APAddress = intMDAddress - remappingBank4[0][0] + remappingBank4[0][1]
else :
APAddress = intMDAddress - remappingBank4[1][0] + remappingBank4[1][1]
APAddress +=0x40000000
else :
print("Can't find remapping address")
APAddress = intMDAddress
APAddress += (MDAddress[3] & 15) << 24
return APAddress.to_bytes(4, "little")
def ParsingMIDRStartAddress(inp) :
inp.seek(remappingBank4[1][1] - DRAMOffset + fileOffset)
stage = 0
ch = inp.read(1)
while ch :
if ord(ch) == ord(EDBGINFO[stage]) :
stage += 1
else :
stage = 0
if stage == len(EDBGINFO) :
return True
ch = inp.read(1)
return False
def ParsingTLV(inp, outp) :
global haveStartGuard, haveEndGuard
typeID = inp.read(1)
#By MDMP_TLV_END = 0
while ord(typeID) != 0:
lens = inp.read(2)
value = inp.read(int.from_bytes(lens, byteorder="little"))
if int.from_bytes(value, "little") & 1 == True :
haveStartGuard = True
if int.from_bytes(value, "little") & 2 == True :
haveEndGuard = True
outp.write(typeID+lens+value)
typeID = inp.read(1)
lens = inp.read(2)
outp.write(typeID+lens)
def StartGuardCheck(inp, outp) :
startGuard = inp.read(1)
if startGuard != b'\xce' :
return False
outp.write(startGuard)
return True
# ToDo: when DHL add end guard, it need to add end guard check
def EndGuardCheck(inp, outp) :
endGuard = inp.read(1)
outp.write(endGuard)
return True
def ProcessMemOnEMI(inp, outp, mdAddress, lens) :
print("Processing mem on EMI : ")
apAddress = ConvertMD2APAddress(mdAddress)
print('MD address', '0x%08x'%int.from_bytes(mdAddress, "little"))
print("AP address", '0x%08x'%int.from_bytes(apAddress, "little"))
DRAMAddress = int.from_bytes(apAddress, "little") - DRAMOffset + fileOffset
print("File offset", '0x%08x'%DRAMAddress)
storeFilePointer = inp.tell()
inp.seek(DRAMAddress, 0)
memData = inp.read(int.from_bytes(lens, "little"))
outp.write(memData)
inp.seek(storeFilePointer, 0)
def ParsingDumpHeader(inp, outp) :
if haveStartGuard == True and StartGuardCheck(inp, outp) == False :
print("Error! Start Guard Missing")
exit()
memType = inp.read(1)
print("Mem type : ", hex(int.from_bytes(memType, "little")))
if memType == b'\xff' :
endDump = inp.read(4)
# end dump check
if endDump != b"\x44\x45\x41\x44" :
print("End Dump Pattern Error!")
exit()
outp.write(memType+endDump)
return memType
# 128 = 0b1000 0000
if ord(memType) & 128 :
headerType = 1
else :
headerType = 0
outp.write(memType)
address = inp.read(4)
outp.write(address)
addressMapping = -1
if headerType == 1 :
addressMapping = inp.read(4)
outp.write(addressMapping)
length = inp.read(2)
outp.write(length)
if length == b'\xff\xff' :
length = inp.read(4)
outp.write(length)
print("Length: ", int.from_bytes(length, "little"))
skip = inp.read(4)
if skip == bytes(SKIPPATTERN, "ascii") :
ProcessMemOnEMI(inp, outp, address, length)
else :
inp.seek(-4, 1)
print('MD address', '0x%08x'%int.from_bytes(address, "little"))
rawData = inp.read(int.from_bytes(length, "little"))
outp.write(rawData)
if haveEndGuard == True and EndGuardCheck(inp, outp) == False:
print("Error! End Guard Missing")
return memType
def RebuildFullMemoryDumpFile(inputFileName, outputFileName) :
inp = open(inputFileName, "rb")
outp = open(outputFileName, "wb")
if ParsingMIDRStartAddress(inp) == False :
print("Not Found MIDR")
exit()
for byte in EDBGINFO :
outp.write(ord(byte).to_bytes(1, "little"))
ParsingTLV(inp, outp)
memType = ParsingDumpHeader(inp, outp)
while memType != b'\xff' :
print("\n======\n")
memType = ParsingDumpHeader(inp, outp)
inp.close()
outp.close()
def GetDRAMFileOffset(inputFileName) :
global fileOffset
proc = Popen("readelf -l -W %s"%inputFileName, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
commandResult = proc.communicate()
if commandResult[1] != b'' :
print(str(proc.communicate()[1], 'utf-8'))
print("%s is invalid!! Please use the correct SYS_COREDUMP file!!" %inputFileName)
exit()
result = commandResult[0]
result = str(result, 'utf-8')
SRAMPos = result.find("LOAD")
DRAMPos = result.find("LOAD", SRAMPos + 1)
hexStart = result.find("0x", DRAMPos)
hexEnd = result.find(" ", hexStart)
fileOffset = int(result[hexStart : hexEnd], 16)
print("File offset : 0x%08x" %fileOffset)
def MRDUMPToolParser(inputFileName, elf, dumpToolPath) :
proc = Popen("%s %s %s "%(dumpToolPath, elf, inputFileName), shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
result = proc.communicate("print /x modem_sys[0].mem_layout.md_bank0.base_ap_view_phy\n\
print /x modem_sys[0].mem_layout.md_bank0.base_md_view_phy\n\
print /x modem_sys[0].mem_layout.md_bank4_noncacheable.base_ap_view_phy\n\
print /x modem_sys[0].mem_layout.md_bank4_noncacheable.base_md_view_phy\n\
print /x modem_sys[0].mem_layout.md_bank4_cacheable.base_ap_view_phy\n\
print /x modem_sys[0].mem_layout.md_bank4_cacheable.base_md_view_phy\n".encode())[0]
result = str(result, 'utf-8')
remappingBank0[1] = int(result[result.find("$1")+4 : result.find('\n', result.find("$1"))], 16)
remappingBank0[0] = int(result[result.find("$2")+4 : result.find('\n', result.find("$2"))], 16)
remappingBank4[0][1] = int(result[result.find("$3")+4 : result.find('\n', result.find("$3"))], 16)
remappingBank4[0][0] = int(result[result.find("$4")+4 : result.find('\n', result.find("$4"))], 16)
remappingBank4[1][1] = int(result[result.find("$5")+4 : result.find('\n', result.find("$5"))], 16)
remappingBank4[1][0] = int(result[result.find("$6")+4 : result.find('\n', result.find("$6"))], 16)
print("Bank0/1 \t\t MD address: 0x%08x <-> AP address 0x%08x"%(remappingBank0[0], remappingBank0[1]))
print("Bank4(noncacheable) \t MD address: 0x%08x <-> AP address 0x%08x"%(remappingBank4[0][0], remappingBank4[0][1]))
print("Bank4(cacheable) \t MD address: 0x%08x <-> AP address 0x%08x"%(remappingBank4[1][0], remappingBank4[1][1]))
GetDRAMFileOffset(inputFileName)
return
def GetAPInfo(coreDumpFile) :
checkInfoList = ["BRANCH_INFO=" , "VERNO=", "SUBTARGET=", "PLATFORM="]
apLoadInfo = []
inp = open(coreDumpFile, "rb")
for info in checkInfoList :
stage = 0
tempInfo = ""
wantInfo = ""
ch = inp.read(1)
while ch :
if ord(ch) == ord(info[stage]) :
stage += 1
tempInfo = tempInfo + ch.decode()
else :
stage = 0
tempInfo = ""
if stage == len(info) :
ch = inp.read(1)
if (ord(ch) >= ord('A') and ord(ch) <= ord('Z')) or (ord(ch) >= ord('a') and ord(ch) <= ord('z')) :
while ord(ch) != ord('\n') :
wantInfo = wantInfo + ch.decode()
ch = inp.read(1)
apLoadInfo.append(wantInfo)
break
else :
stage = 0
tempInfo = ""
ch = inp.read(1)
if len(checkInfoList) != len(apLoadInfo):
return []
return apLoadInfo
def AutoFindAPELF(coreDumpFile) :
print ("======\nAuto find AP ELF mode...")
apInfo = GetAPInfo(coreDumpFile)
if len(apInfo) == 0 :
print("\nCan't find AP version info in full RAM dump!\nPlease enter the vmliux path manually!")
exit()
print("\nBRANCH_INFO:\t%s\nVERNO:\t\t%s\nSUBTARGET:\t%s\nPLATFORM:\t%s\n" %(apInfo[0], apInfo[1], apInfo[2], apInfo[3]))
vmlinuxPath = apSymbolPathLINUX + apInfo[0] + "/Symbols/" + apInfo[1] + "/" + apInfo[3] + "/" + apInfo[2] + "/vmlinux"
if os.path.isfile(vmlinuxPath) == False :
print("Can't find the vmlinux in %s !\nPlease update your AP version or enter the vmliux path manually!" %vmlinuxPath)
exit()
print("vmlinux path : " + vmlinuxPath + "\n")
return vmlinuxPath
# Manual input mode (for backup)
def ManualInput() :
bank0StartAddress = input("Please enter the AP address mapping to Bank0/1 (0x00000000) :\n")
bank4MDCacheableStartAddress = input("Please enter the Bank4 cacheable MD address :\n")
bank4CacheableStartAddress = input("Please enter the AP address mapping to Bank4 (cacheable) :\n")
bank4UncacheableStartAddress = input("Please enter the AP address mapping to Bank4 (uncacheable) :\n")
remappingBank0[1] = int(bank0StartAddress, 16)
remappingBank4[1][0] = int(bank4MDCacheableStartAddress, 16)
remappingBank4[1][1] = int(bank4CacheableStartAddress, 16)
remappingBank4[0][1] = int(bank4UncacheableStartAddress, 16)
def ParseMRDUMPBIHeader(coreDumpFile) :
inp = open(coreDumpFile, "rb")
stage = 0
currentPos = 1
foundMRDUMPBI = False
GetDRAMFileOffset(coreDumpFile)
ch = inp.read(1)
# MRDUMPBI should be stored before DRAM dump
while ch and currentPos <= fileOffset:
# Parsing MRDUMPBI to find MD/AP remapping info
if ord(ch) == ord(MRDUMPBI[stage]) :
stage += 1
else :
stage = 0
currentPos = currentPos + 1
if stage == len(MRDUMPBI) :
# Get AP/MD address remapping info
remappingBank0[1] = int.from_bytes(inp.read(8), "little")
remappingBank0[0] = int.from_bytes(inp.read(8), "little")
remappingBank4[1][1] = int.from_bytes(inp.read(8), "little")
remappingBank4[1][0] = int.from_bytes(inp.read(8), "little")
remappingBank4[0][1] = int.from_bytes(inp.read(8), "little")
remappingBank4[0][0] = int.from_bytes(inp.read(8), "little")
print("Bank0/1 \t\t MD address: 0x%08x <-> AP address: 0x%08x"%(remappingBank0[0], remappingBank0[1]))
print("Bank4(noncacheable) \t MD address: 0x%08x <-> AP address: 0x%08x"%(remappingBank4[0][0], remappingBank4[0][1]))
print("Bank4(cacheable) \t MD address: 0x%08x <-> AP address: 0x%08x"%(remappingBank4[1][0], remappingBank4[1][1]))
foundMRDUMPBI = True
break
ch = inp.read(1)
if foundMRDUMPBI == False :
print("\nCan't find MRDUMPBI! The AP version doesn't provide AP/MD address remapping info!!\n\nEnter maunal input mode: \n")
ManualInput()
if __name__ == "__main__":
print("MIDR dump post-processing script V %s"%version)
inputFileName, outputFileName, useMRDumptool, elf, dumpToolPath = ParsingArgument()
if useMRDumptool == "True" :
# Legacy version : need mrdump tool and vmlinux file to get AP/MD address remapping
if os.name != "posix" :
print("\nmrdump tool only can run on Linux!")
exit()
# Test mrdump tool
proc = Popen("%s "%dumpToolPath, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
result = proc.communicate()
if str(result[1], 'utf-8') != "" :
print(str(result[1], 'utf-8'))
print("Please enter the correct mrdump tool path!")
exit()
if elf == '' :
elf = AutoFindAPELF(inputFileName)
print("======\nGet MD/AP address remapping information by mrdump tool...")
MRDUMPToolParser(inputFileName, elf, dumpToolPath)
print("\nDone!\n")
else :
# From V1.2 : AP write AP/MD address remapping info to SYS_COREDUMP header, we can parse header to get those info
print("======\nGet MD/AP address remapping information from dump header...")
ParseMRDUMPBIHeader(inputFileName)
print("\nDone!\n")
print("======\n\nGenerating FULL Memory Dump File...\n")
RebuildFullMemoryDumpFile(inputFileName, outputFileName)
print("Done!")