blob: 13c75583f7880ed21fd5b60ccfee3782d3336dcf [file] [log] [blame]
rjw6c1fd8f2022-11-30 14:33:01 +08001import argparse
2import os
3from subprocess import Popen, PIPE
4
5version = "1.2"
6#Fixed Pattern
7EDBGINFO = "EDBGINFO\x05\x00\x00\x00"
8SKIPPATTERN = "\x53\x4B\x49\x50"
9MRDUMPBI = "MRDUMPBI"
10
11#Start/End Guard Eable
12haveStartGuard = False
13haveEndGuard = False
14
15#Default AP vmlinux path (for auto find function)
16apSymbolPathWIN = "\\\\mtksfs00\\srv_colgin_ci\\image\\SanityLoad\\"
17apSymbolPathLINUX = "/proj/srv_colgin_ci/image/SanityLoad/"
18
19#Default value (would be overwitten)
20remappingBank4 = [[0x40000000, 0x8e000000], [0x46000000, 0x84000000]]
21remappingBank0 = [0x00000000, 0xae000000]
22DRAMOffset = 0x40000000
23fileOffset = 0x00004000
24
25def ParsingArgument() :
26 parser = argparse.ArgumentParser()
27 parser.add_argument("-i", type=str, dest="core_dump", required=True, help="Input full ram dump path")
28 parser.add_argument("-o", type=str, dest="output", required=True, help="Output memory dump file path")
29 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")
30 parser.add_argument("-e", "--elf", type=str, default='', dest="vmlinux", help="Input vmlinux (ELF) path")
31 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)\
32 https://wiki.mediatek.inc/pages/viewpage.action?pageId=58229130")
33
34 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)
35
36def ConvertMD2APAddress(MDAddress) :
37 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 :
38 bank = 0
39 elif MDAddress[-1] >> 4 == 1 or MDAddress[-1] >> 4 == 7 :
40 bank = 1
41 elif MDAddress[-1] >> 4 == 4 :
42 bank = 4
43 else :
44 bank = -1
45
46 intMDAddress = int.from_bytes(MDAddress[0:3], "little")
47
48 if bank == 0 :
49 APAddress = intMDAddress - remappingBank0[0] + remappingBank0[1]
50 elif bank == 1 :
51 APAddress = intMDAddress - remappingBank0[0] + remappingBank0[1] + 0x02000000
52 elif bank == 4 :
53 if MDAddress[-1] & 15 < 6 :
54 APAddress = intMDAddress - remappingBank4[0][0] + remappingBank4[0][1]
55 else :
56 APAddress = intMDAddress - remappingBank4[1][0] + remappingBank4[1][1]
57 APAddress +=0x40000000
58 else :
59 print("Can't find remapping address")
60 APAddress = intMDAddress
61
62 APAddress += (MDAddress[3] & 15) << 24
63
64 return APAddress.to_bytes(4, "little")
65
66def ParsingMIDRStartAddress(inp) :
67 inp.seek(remappingBank4[1][1] - DRAMOffset + fileOffset)
68
69 stage = 0
70 ch = inp.read(1)
71 while ch :
72 if ord(ch) == ord(EDBGINFO[stage]) :
73 stage += 1
74 else :
75 stage = 0
76
77 if stage == len(EDBGINFO) :
78 return True
79
80 ch = inp.read(1)
81
82 return False
83
84def ParsingTLV(inp, outp) :
85 global haveStartGuard, haveEndGuard
86 typeID = inp.read(1)
87
88 #By MDMP_TLV_END = 0
89 while ord(typeID) != 0:
90 lens = inp.read(2)
91 value = inp.read(int.from_bytes(lens, byteorder="little"))
92
93 if int.from_bytes(value, "little") & 1 == True :
94 haveStartGuard = True
95 if int.from_bytes(value, "little") & 2 == True :
96 haveEndGuard = True
97
98 outp.write(typeID+lens+value)
99 typeID = inp.read(1)
100
101 lens = inp.read(2)
102 outp.write(typeID+lens)
103
104def StartGuardCheck(inp, outp) :
105 startGuard = inp.read(1)
106
107 if startGuard != b'\xce' :
108 return False
109
110 outp.write(startGuard)
111 return True
112
113# ToDo: when DHL add end guard, it need to add end guard check
114def EndGuardCheck(inp, outp) :
115 endGuard = inp.read(1)
116 outp.write(endGuard)
117 return True
118
119def ProcessMemOnEMI(inp, outp, mdAddress, lens) :
120 print("Processing mem on EMI : ")
121 apAddress = ConvertMD2APAddress(mdAddress)
122 print('MD address', '0x%08x'%int.from_bytes(mdAddress, "little"))
123 print("AP address", '0x%08x'%int.from_bytes(apAddress, "little"))
124 DRAMAddress = int.from_bytes(apAddress, "little") - DRAMOffset + fileOffset
125 print("File offset", '0x%08x'%DRAMAddress)
126 storeFilePointer = inp.tell()
127 inp.seek(DRAMAddress, 0)
128 memData = inp.read(int.from_bytes(lens, "little"))
129 outp.write(memData)
130 inp.seek(storeFilePointer, 0)
131
132
133def ParsingDumpHeader(inp, outp) :
134 if haveStartGuard == True and StartGuardCheck(inp, outp) == False :
135 print("Error! Start Guard Missing")
136 exit()
137
138 memType = inp.read(1)
139 print("Mem type : ", hex(int.from_bytes(memType, "little")))
140 if memType == b'\xff' :
141 endDump = inp.read(4)
142 # end dump check
143 if endDump != b"\x44\x45\x41\x44" :
144 print("End Dump Pattern Error!")
145 exit()
146 outp.write(memType+endDump)
147 return memType
148
149 # 128 = 0b1000 0000
150 if ord(memType) & 128 :
151 headerType = 1
152 else :
153 headerType = 0
154 outp.write(memType)
155
156 address = inp.read(4)
157 outp.write(address)
158 addressMapping = -1
159
160 if headerType == 1 :
161 addressMapping = inp.read(4)
162 outp.write(addressMapping)
163
164 length = inp.read(2)
165 outp.write(length)
166
167 if length == b'\xff\xff' :
168 length = inp.read(4)
169 outp.write(length)
170 print("Length: ", int.from_bytes(length, "little"))
171
172 skip = inp.read(4)
173
174 if skip == bytes(SKIPPATTERN, "ascii") :
175 ProcessMemOnEMI(inp, outp, address, length)
176 else :
177 inp.seek(-4, 1)
178 print('MD address', '0x%08x'%int.from_bytes(address, "little"))
179 rawData = inp.read(int.from_bytes(length, "little"))
180 outp.write(rawData)
181
182 if haveEndGuard == True and EndGuardCheck(inp, outp) == False:
183 print("Error! End Guard Missing")
184
185 return memType
186
187def RebuildFullMemoryDumpFile(inputFileName, outputFileName) :
188 inp = open(inputFileName, "rb")
189 outp = open(outputFileName, "wb")
190
191 if ParsingMIDRStartAddress(inp) == False :
192 print("Not Found MIDR")
193 exit()
194
195 for byte in EDBGINFO :
196 outp.write(ord(byte).to_bytes(1, "little"))
197
198 ParsingTLV(inp, outp)
199 memType = ParsingDumpHeader(inp, outp)
200
201 while memType != b'\xff' :
202 print("\n======\n")
203 memType = ParsingDumpHeader(inp, outp)
204
205 inp.close()
206 outp.close()
207
208def GetDRAMFileOffset(inputFileName) :
209 global fileOffset
210
211 proc = Popen("readelf -l -W %s"%inputFileName, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
212 commandResult = proc.communicate()
213
214 if commandResult[1] != b'' :
215 print(str(proc.communicate()[1], 'utf-8'))
216 print("%s is invalid!! Please use the correct SYS_COREDUMP file!!" %inputFileName)
217 exit()
218
219 result = commandResult[0]
220 result = str(result, 'utf-8')
221
222 SRAMPos = result.find("LOAD")
223 DRAMPos = result.find("LOAD", SRAMPos + 1)
224 hexStart = result.find("0x", DRAMPos)
225 hexEnd = result.find(" ", hexStart)
226 fileOffset = int(result[hexStart : hexEnd], 16)
227
228 print("File offset : 0x%08x" %fileOffset)
229
230def MRDUMPToolParser(inputFileName, elf, dumpToolPath) :
231 proc = Popen("%s %s %s "%(dumpToolPath, elf, inputFileName), shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
232
233 result = proc.communicate("print /x modem_sys[0].mem_layout.md_bank0.base_ap_view_phy\n\
234 print /x modem_sys[0].mem_layout.md_bank0.base_md_view_phy\n\
235 print /x modem_sys[0].mem_layout.md_bank4_noncacheable.base_ap_view_phy\n\
236 print /x modem_sys[0].mem_layout.md_bank4_noncacheable.base_md_view_phy\n\
237 print /x modem_sys[0].mem_layout.md_bank4_cacheable.base_ap_view_phy\n\
238 print /x modem_sys[0].mem_layout.md_bank4_cacheable.base_md_view_phy\n".encode())[0]
239
240 result = str(result, 'utf-8')
241 remappingBank0[1] = int(result[result.find("$1")+4 : result.find('\n', result.find("$1"))], 16)
242 remappingBank0[0] = int(result[result.find("$2")+4 : result.find('\n', result.find("$2"))], 16)
243 remappingBank4[0][1] = int(result[result.find("$3")+4 : result.find('\n', result.find("$3"))], 16)
244 remappingBank4[0][0] = int(result[result.find("$4")+4 : result.find('\n', result.find("$4"))], 16)
245 remappingBank4[1][1] = int(result[result.find("$5")+4 : result.find('\n', result.find("$5"))], 16)
246 remappingBank4[1][0] = int(result[result.find("$6")+4 : result.find('\n', result.find("$6"))], 16)
247 print("Bank0/1 \t\t MD address: 0x%08x <-> AP address 0x%08x"%(remappingBank0[0], remappingBank0[1]))
248 print("Bank4(noncacheable) \t MD address: 0x%08x <-> AP address 0x%08x"%(remappingBank4[0][0], remappingBank4[0][1]))
249 print("Bank4(cacheable) \t MD address: 0x%08x <-> AP address 0x%08x"%(remappingBank4[1][0], remappingBank4[1][1]))
250
251 GetDRAMFileOffset(inputFileName)
252
253 return
254
255def GetAPInfo(coreDumpFile) :
256 checkInfoList = ["BRANCH_INFO=" , "VERNO=", "SUBTARGET=", "PLATFORM="]
257 apLoadInfo = []
258
259 inp = open(coreDumpFile, "rb")
260 for info in checkInfoList :
261 stage = 0
262 tempInfo = ""
263 wantInfo = ""
264
265 ch = inp.read(1)
266 while ch :
267 if ord(ch) == ord(info[stage]) :
268 stage += 1
269 tempInfo = tempInfo + ch.decode()
270 else :
271 stage = 0
272 tempInfo = ""
273
274 if stage == len(info) :
275 ch = inp.read(1)
276 if (ord(ch) >= ord('A') and ord(ch) <= ord('Z')) or (ord(ch) >= ord('a') and ord(ch) <= ord('z')) :
277 while ord(ch) != ord('\n') :
278 wantInfo = wantInfo + ch.decode()
279 ch = inp.read(1)
280 apLoadInfo.append(wantInfo)
281 break
282 else :
283 stage = 0
284 tempInfo = ""
285
286 ch = inp.read(1)
287 if len(checkInfoList) != len(apLoadInfo):
288 return []
289 return apLoadInfo
290
291
292def AutoFindAPELF(coreDumpFile) :
293 print ("======\nAuto find AP ELF mode...")
294 apInfo = GetAPInfo(coreDumpFile)
295 if len(apInfo) == 0 :
296 print("\nCan't find AP version info in full RAM dump!\nPlease enter the vmliux path manually!")
297 exit()
298
299 print("\nBRANCH_INFO:\t%s\nVERNO:\t\t%s\nSUBTARGET:\t%s\nPLATFORM:\t%s\n" %(apInfo[0], apInfo[1], apInfo[2], apInfo[3]))
300
301 vmlinuxPath = apSymbolPathLINUX + apInfo[0] + "/Symbols/" + apInfo[1] + "/" + apInfo[3] + "/" + apInfo[2] + "/vmlinux"
302
303 if os.path.isfile(vmlinuxPath) == False :
304 print("Can't find the vmlinux in %s !\nPlease update your AP version or enter the vmliux path manually!" %vmlinuxPath)
305 exit()
306
307 print("vmlinux path : " + vmlinuxPath + "\n")
308
309 return vmlinuxPath
310
311
312# Manual input mode (for backup)
313def ManualInput() :
314 bank0StartAddress = input("Please enter the AP address mapping to Bank0/1 (0x00000000) :\n")
315 bank4MDCacheableStartAddress = input("Please enter the Bank4 cacheable MD address :\n")
316 bank4CacheableStartAddress = input("Please enter the AP address mapping to Bank4 (cacheable) :\n")
317 bank4UncacheableStartAddress = input("Please enter the AP address mapping to Bank4 (uncacheable) :\n")
318
319 remappingBank0[1] = int(bank0StartAddress, 16)
320 remappingBank4[1][0] = int(bank4MDCacheableStartAddress, 16)
321 remappingBank4[1][1] = int(bank4CacheableStartAddress, 16)
322 remappingBank4[0][1] = int(bank4UncacheableStartAddress, 16)
323
324def ParseMRDUMPBIHeader(coreDumpFile) :
325 inp = open(coreDumpFile, "rb")
326 stage = 0
327 currentPos = 1
328 foundMRDUMPBI = False
329
330 GetDRAMFileOffset(coreDumpFile)
331
332 ch = inp.read(1)
333
334 # MRDUMPBI should be stored before DRAM dump
335 while ch and currentPos <= fileOffset:
336 # Parsing MRDUMPBI to find MD/AP remapping info
337 if ord(ch) == ord(MRDUMPBI[stage]) :
338 stage += 1
339 else :
340 stage = 0
341
342 currentPos = currentPos + 1
343
344 if stage == len(MRDUMPBI) :
345 # Get AP/MD address remapping info
346 remappingBank0[1] = int.from_bytes(inp.read(8), "little")
347 remappingBank0[0] = int.from_bytes(inp.read(8), "little")
348 remappingBank4[1][1] = int.from_bytes(inp.read(8), "little")
349 remappingBank4[1][0] = int.from_bytes(inp.read(8), "little")
350 remappingBank4[0][1] = int.from_bytes(inp.read(8), "little")
351 remappingBank4[0][0] = int.from_bytes(inp.read(8), "little")
352
353 print("Bank0/1 \t\t MD address: 0x%08x <-> AP address: 0x%08x"%(remappingBank0[0], remappingBank0[1]))
354 print("Bank4(noncacheable) \t MD address: 0x%08x <-> AP address: 0x%08x"%(remappingBank4[0][0], remappingBank4[0][1]))
355 print("Bank4(cacheable) \t MD address: 0x%08x <-> AP address: 0x%08x"%(remappingBank4[1][0], remappingBank4[1][1]))
356
357 foundMRDUMPBI = True
358
359 break
360
361 ch = inp.read(1)
362
363 if foundMRDUMPBI == False :
364 print("\nCan't find MRDUMPBI! The AP version doesn't provide AP/MD address remapping info!!\n\nEnter maunal input mode: \n")
365 ManualInput()
366
367
368
369if __name__ == "__main__":
370 print("MIDR dump post-processing script V %s"%version)
371
372 inputFileName, outputFileName, useMRDumptool, elf, dumpToolPath = ParsingArgument()
373
374 if useMRDumptool == "True" :
375 # Legacy version : need mrdump tool and vmlinux file to get AP/MD address remapping
376 if os.name != "posix" :
377 print("\nmrdump tool only can run on Linux!")
378 exit()
379
380 # Test mrdump tool
381 proc = Popen("%s "%dumpToolPath, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
382 result = proc.communicate()
383 if str(result[1], 'utf-8') != "" :
384 print(str(result[1], 'utf-8'))
385 print("Please enter the correct mrdump tool path!")
386 exit()
387
388 if elf == '' :
389 elf = AutoFindAPELF(inputFileName)
390
391 print("======\nGet MD/AP address remapping information by mrdump tool...")
392 MRDUMPToolParser(inputFileName, elf, dumpToolPath)
393 print("\nDone!\n")
394 else :
395 # From V1.2 : AP write AP/MD address remapping info to SYS_COREDUMP header, we can parse header to get those info
396 print("======\nGet MD/AP address remapping information from dump header...")
397 ParseMRDUMPBIHeader(inputFileName)
398 print("\nDone!\n")
399
400 print("======\n\nGenerating FULL Memory Dump File...\n")
401 RebuildFullMemoryDumpFile(inputFileName, outputFileName)
402 print("Done!")