Several fixes and improvements

This commit is contained in:
Bjoern Kerler 2021-08-25 16:50:48 +02:00
parent a8e4a753dc
commit f0c6ad156c
12 changed files with 229 additions and 205 deletions

120
mtk
View file

@ -17,7 +17,7 @@ Usage:
mtk.py rs <start_sector> <sectors> <filename> [--parttype=parttype] [--lun=lun] [--preloader=filename] [--loader=filename] [--payload=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1] [--ptype=ptype]
mtk.py w <partitionname> <filename> [--parttype=parttype] [--memory=memtype] [--lun=lun] [--preloader=filename] [--loader=filename] [--payload=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1] [--ptype=ptype]
mtk.py wf <filename> [--parttype=parttype] [--memory=memtype] [--lun=lun] [--preloader=filename] [--loader=filename] [--payload=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1] [--ptype=ptype]
mtk.py wl <directory> [--memory=memtype] [--parttype=parttype] [--lun=lun] [--skip=partnames] [--preloader=filename] [--payload=filename] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1] [--generatekeys=keymode] [--ptype=ptype]
mtk.py wl <directory> [--memory=memtype] [--parttype=parttype] [--lun=lun] [--skip=partnames] [--preloader=filename] [--payload=filename] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1] [--ptype=ptype]
mtk.py e <partitionname> [--parttype=parttype] [--memory=memtype] [--lun=lun] [--preloader=filename] [--loader=filename] [--payload=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1] [--ptype=ptype]
mtk.py footer <filename> [--memory=memtype] [--lun=lun] [--preloader=filename] [--loader=filename] [--payload=filename] [--debugmode] [--vid=vid] [--pid=pid] [--var1=var1]
mtk.py reset [--debugmode] [--vid=vid] [--pid=pid]
@ -80,7 +80,6 @@ Options:
--socid Read Soc ID
--startpartition=startpartition Option for plstage - Boot to (lk, tee1)
"""
import os
import sys
import logging
@ -214,7 +213,7 @@ class Mtk(metaclass=LogBase):
return self
def parse_preloader(preloader):
def parse_preloader(mtk, preloader):
with open(preloader, "rb") as rf:
magic = unpack("<I", rf.read(4))[0]
if magic == 0x014D4D4D:
@ -229,7 +228,7 @@ def parse_preloader(preloader):
rf.seek(jump_offset)
dadata = rf.read(dasize - jump_offset)
else:
daaddr = 0x201000
daaddr = mtk.config.chipconfig.da_payload_addr
rf.seek(0)
dadata = rf.read()
return daaddr, dadata
@ -295,8 +294,8 @@ class Main(metaclass=LogBase):
self.__logger.setLevel(logging.DEBUG)
else:
self.__logger.setLevel(logging.INFO)
interface = -1
self.debug(" ".join(sys.argv))
interface = -1
# pagesize = getint(self.args["--sectorsize"])
mtk = Mtk(loader=self.args["--loader"], loglevel=self.__logger.level, vid=vid, pid=pid, interface=interface,
args=self.args)
@ -358,9 +357,9 @@ class Main(metaclass=LogBase):
filename = self.args["--filename"]
if self.args["--preloader"] is not None:
preloader = self.args["--preloader"]
if os.path.exists(preloader):
daaddr, dadata = parse_preloader(preloader)
if mtk.preloader.init(args=self.args, readsocid=readsocid):
if mtk.preloader.init(args=self.args, readsocid=readsocid):
if os.path.exists(preloader):
daaddr, dadata = parse_preloader(mtk,preloader)
if mtk.config.target_config["daa"]:
mtk = mtk.bypass_security(args=self.args, vid=vid, pid=pid, interface=interface,
readsocid=readsocid, enforcecrash=enforcecrash)
@ -456,7 +455,7 @@ class Main(metaclass=LogBase):
else:
filename = self.args["--filename"]
if os.path.exists(preloader):
daaddr, dadata = parse_preloader(preloader)
daaddr, dadata = parse_preloader(mtk, preloader)
if mtk.preloader.init(args=self.args, readsocid=readsocid):
if mtk.config.target_config["daa"]:
mtk = mtk.bypass_security(args=self.args, vid=vid, pid=pid, interface=interface,
@ -712,6 +711,8 @@ class Main(metaclass=LogBase):
exit(1)
if parttype == "user" or parttype is None:
i = 0
self.info("Requesting available partitions ....")
gpttable = mtk.daloader.get_partition_data(self.args, parttype=parttype)
for partition in partitions:
partfilename = filenames[i]
i += 1
@ -720,24 +721,34 @@ class Main(metaclass=LogBase):
length=0x16000,
filename=partfilename, parttype=parttype)
continue
res = mtk.daloader.detect_partition(self.args, partition, parttype)
if res[0]:
rpartition = res[1]
mtk.daloader.readflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
filename=partfilename, parttype=parttype)
print(f"Dumped sector {str(rpartition.sector)} with sector count " +
f"{str(rpartition.sectors)} as {partfilename}.")
else:
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
for rpartition in res[1]:
self.info(rpartition.name)
rpartition = None
for gptentry in gpttable:
if gptentry.name.lower()==partition.lower():
rpartition=gptentry
break
if rpartition is not None:
self.info(f"Dumping partition {rpartition.name}")
if mtk.daloader.readflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
filename=partfilename, parttype=parttype):
self.info(f"Dumped sector {str(rpartition.sector)} with sector count " +
f"{str(rpartition.sectors)} as {partfilename}.")
else:
self.info(f"Failed to dump sector {str(rpartition.sector)} with sector count " +
f"{str(rpartition.sectors)} as {partfilename}.")
else:
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
for rpartition in gpttable:
self.info(rpartition.name)
else:
i = 0
for partfilename in filenames:
pos = 0
mtk.daloader.readflash(addr=pos, length=0xFFFFFFFF, filename=partfilename, parttype=parttype)
print(f"Dumped partition {str(partitionname)} as {partfilename}.")
if mtk.daloader.readflash(addr=pos, length=0xFFFFFFFF, filename=partfilename, parttype=parttype):
print(f"Dumped partition {str(partitionname)} as {partfilename}.")
else:
print(f"Failed to dump partition {str(partitionname)} as {partfilename}.")
i += 1
mtk.daloader.close()
self.close()
@ -792,8 +803,10 @@ class Main(metaclass=LogBase):
else:
length = mtk.daloader.daconfig.flashsize
print(f"Dumping sector 0 with flash size {hex(length)} as {filename}.")
mtk.daloader.readflash(addr=0, length=length, filename=filename, parttype=parttype)
print(f"Dumped sector 0 with flash size {hex(length)} as {filename}.")
if mtk.daloader.readflash(addr=0, length=length, filename=filename, parttype=parttype):
print(f"Dumped sector 0 with flash size {hex(length)} as {filename}.")
else:
print(f"Failed to dump sector 0 with flash size {hex(length)} as {filename}.")
mtk.daloader.close()
self.close()
elif self.args["rs"]:
@ -801,10 +814,12 @@ class Main(metaclass=LogBase):
sectors = getint(self.args["<sectors>"])
filename = self.args["<filename>"]
parttype = self.args["--parttype"]
mtk.daloader.readflash(addr=start * mtk.daloader.daconfig.pagesize,
if mtk.daloader.readflash(addr=start * mtk.daloader.daconfig.pagesize,
length=sectors * mtk.daloader.daconfig.pagesize,
filename=filename, parttype=parttype)
print(f"Dumped sector {str(start)} with sector count {str(sectors)} as {filename}.")
filename=filename, parttype=parttype):
print(f"Dumped sector {str(start)} with sector count {str(sectors)} as {filename}.")
else:
print(f"Failed to dump sector {str(start)} with sector count {str(sectors)} as {filename}.")
mtk.daloader.close()
self.close()
elif self.args["footer"]:
@ -863,9 +878,9 @@ class Main(metaclass=LogBase):
if res[0]:
rpartition = res[1]
if mtk.daloader.writeflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
filename=partfilename,
partitionname=partition, parttype=parttype):
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
filename=partfilename,
partitionname=partition, parttype=parttype):
print(
f"Wrote {partfilename} to sector {str(rpartition.sector)} with " +
f"sector count {str(rpartition.sectors)}.")
@ -881,13 +896,14 @@ class Main(metaclass=LogBase):
pos = 0
for partfilename in filenames:
size = os.stat(partfilename).st_size
if mtk.daloader.writeflash(addr=pos, length=size, filename=partfilename, partitionname=partitionname,
parttype=parttype):
if mtk.daloader.writeflash(addr=pos, length=size, filename=partfilename,
partitionname=partitionname,
parttype=parttype):
print(f"Wrote {partfilename} to sector {str(pos // 0x200)} with " +
f"sector count {str(size)}.")
else:
print(f"Failed to write {partfilename} to sector {str(pos // 0x200)} with " +
f"sector count {str(size)}.")
f"sector count {str(size)}.")
psize = size // 0x200 * 0x200
if size % 0x200 != 0:
psize += 0x200
@ -911,9 +927,9 @@ class Main(metaclass=LogBase):
if partition == "gpt":
self.info(f"Writing partition {partition}")
if mtk.daloader.writeflash(addr=0,
length=os.stat(partfilename).st_size,
filename=partfilename,
partitionname=partition, parttype=parttype):
length=os.stat(partfilename).st_size,
filename=partfilename,
partitionname=partition, parttype=parttype):
print(f"Wrote {partition} to sector {str(0)}")
else:
print(f"Failed to write {partition} to sector {str(0)}")
@ -922,9 +938,9 @@ class Main(metaclass=LogBase):
if res[0]:
rpartition = res[1]
if mtk.daloader.writeflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
filename=partfilename,
partitionname=partition, parttype=parttype):
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
filename=partfilename,
partitionname=partition, parttype=parttype):
print(
f"Wrote {partfilename} to sector {str(rpartition.sector)} with " +
f"sector count {str(rpartition.sectors)}.")
@ -941,8 +957,9 @@ class Main(metaclass=LogBase):
partition = os.path.basename(partfilename)
partition = os.path.splitext(partition)[0]
self.info(f"Writing filename {partfilename}")
if mtk.daloader.writeflash(addr=pos, length=size, filename=partfilename, partitionname=partition,
parttype=parttype):
if mtk.daloader.writeflash(addr=pos, length=size, filename=partfilename,
partitionname=partition,
parttype=parttype):
print(f"Wrote {partfilename} to sector {str(pos // 0x200)} with " +
f"sector count {str(size)}.")
else:
@ -966,13 +983,13 @@ class Main(metaclass=LogBase):
if res[0]:
rpartition = res[1]
if mtk.daloader.formatflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
partitionname=partition, parttype=parttype):
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
partitionname=partition, parttype=parttype):
print(
f"Formatted sector {str(rpartition.sector)} with " +
f"sector count {str(rpartition.sectors)}.")
else:
print(
print(
f"Failed to format sector {str(rpartition.sector)} with " +
f"sector count {str(rpartition.sectors)}.")
else:
@ -982,7 +999,8 @@ class Main(metaclass=LogBase):
else:
pos = 0
for partitionname in partitions:
mtk.daloader.formatflash(addr=pos, length=0xF000000, partitionname=partitionname, parttype=parttype,
mtk.daloader.formatflash(addr=pos, length=0xF000000, partitionname=partitionname,
parttype=parttype,
display=True)
print(f"Formatted sector {str(pos // 0x200)}")
mtk.daloader.close()
@ -995,14 +1013,14 @@ class Main(metaclass=LogBase):
for partfilename in filenames:
size = os.stat(partfilename).st_size // 0x200 * 0x200
if mtk.daloader.writeflash(addr=pos,
length=size,
filename=partfilename,
partitionname=None, parttype=parttype):
length=size,
filename=partfilename,
partitionname=None, parttype=parttype):
print(f"Wrote {partfilename} to sector {str(pos // 0x200)} with " +
f"sector count {str(size // 0x200)}.")
f"sector count {str(size // 0x200)}.")
else:
print(f"Failed to write {partfilename} to sector {str(pos // 0x200)} with " +
f"sector count {str(size // 0x200)}.")
f"sector count {str(size // 0x200)}.")
mtk.daloader.close()
self.close()
elif self.args["reset"]:
@ -1011,5 +1029,5 @@ class Main(metaclass=LogBase):
if __name__ == '__main__':
print("MTK Flash/Exploit Client V1.42 (c) B.Kerler 2018-2021")
print("MTK Flash/Exploit Client V1.41 (c) B.Kerler 2018-2021")
mtk = Main().run()

View file

@ -5,10 +5,9 @@ import sys
import logging
import os
import time
import array
from struct import pack, unpack
from binascii import hexlify
from mtkclient.Library.utils import LogBase, print_progress, read_object, logsetup
from mtkclient.Library.utils import LogBase, progress, read_object, logsetup
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.daconfig import DaStorage, EMMC_PartitionType
from mtkclient.Library.partition import Partition
@ -492,9 +491,6 @@ class DALegacy(metaclass=LogBase):
def __init__(self, mtk, daconfig, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel)
self.prog = 0
self.progpos = 0
self.progtime = 0
self.emmc = None
self.nand = None
self.nor = None
@ -513,35 +509,9 @@ class DALegacy(metaclass=LogBase):
self.sectorsize = self.daconfig.pagesize
self.totalsectors = self.daconfig.flashsize
self.partition = Partition(self.mtk, self.readflash, self.read_pmt, loglevel)
self.progress = progress(self.daconfig.pagesize)
self.pathconfig = pathconfig()
def show_progress(self, prefix, pos, total, display=True):
t0 = time.time()
if pos == 0:
self.prog = 0
self.progtime = time.time()
self.progpos = pos
prog = round(float(pos) / float(total) * float(100), 1)
if prog > self.prog:
if display:
tdiff = t0 - self.progtime
datasize = (pos - self.progpos) // 1024 // 1024
if datasize!=0:
try:
throughput = datasize // tdiff
except:
throughput = 0
else:
throughput = 0
print_progress(prog, 100, prefix='Progress:',
suffix=prefix + ' (Sector %d of %d) %0.2f MB/s' %
(pos // self.daconfig.pagesize,
total // self.daconfig.pagesize,
throughput), bar_length=50)
self.prog = prog
self.progpos = pos
self.progtime = t0
def read_pmt(self): # A5
class GptEntries:
partentries = []
@ -725,14 +695,14 @@ class DALegacy(metaclass=LogBase):
self.info("DRAM config needed for : " + hexlify(draminfo).decode('utf-8'))
if self.daconfig.emi is None:
found = False
for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_payloads_path(), 'Preloader')):
for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_loader_path(), 'Preloader')):
for file in files:
with open(os.path.join(root, file), "rb") as rf:
data = rf.read()
if pdram[0] in data or pdram[1] in data:
preloader = os.path.join(root, file)
print("Detected preloader: " + preloader)
self.daconfig.emi = self.daconfig.extract_emi
self.daconfig.extract_emi(preloader,True)
found = True
break
if found:
@ -1036,7 +1006,7 @@ class DALegacy(metaclass=LogBase):
if filename != "":
with open(filename, "rb") as rf:
rf.seek(offset)
self.show_progress("Write", 0, 100, display)
self.progress.show_progress("Write", 0, 100, display)
self.usbwrite(self.Cmd.SDMMC_WRITE_DATA_CMD)
self.usbwrite(pack(">B", storage))
self.usbwrite(pack(">B", parttype))
@ -1057,9 +1027,9 @@ class DALegacy(metaclass=LogBase):
if self.usbread(1) != self.Rsp.CONT_CHAR:
self.error("Data ack failed for sdmmc_write_data")
return False
self.show_progress("Write",offset,length,display)
self.progress.show_progress("Write",offset,length,display)
offset += count
self.show_progress("Write", 100, 100, display)
self.progress.show_progress("Write", 100, 100, display)
return True
def sdmmc_write_image(self, addr, length, filename, display=True):
@ -1077,7 +1047,7 @@ class DALegacy(metaclass=LogBase):
ack = unpack(">B", self.usbread(1))[0]
if ack == self.Rsp.ACK[0]:
self.usbwrite(self.Rsp.ACK)
self.show_progress("Write", 0, 100, display)
self.progress.show_progress("Write", 0, 100, display)
checksum = 0
bytestowrite = length
while bytestowrite > 0:
@ -1085,7 +1055,7 @@ class DALegacy(metaclass=LogBase):
for i in range(0, size, 0x400):
data = bytearray(rf.read(size))
pos = length - bytestowrite
self.show_progress("Write", pos, length, display)
self.progress.show_progress("Write", pos, length, display)
if self.usbwrite(data):
bytestowrite -= size
if bytestowrite == 0:
@ -1101,7 +1071,7 @@ class DALegacy(metaclass=LogBase):
return True
else:
self.usbwrite(self.Rsp.ACK)
self.show_progress("Write", 100, 100, display)
self.progress.show_progress("Write", 100, 100, display)
return True
return True
@ -1228,7 +1198,7 @@ class DALegacy(metaclass=LogBase):
self.usbread(4)
self.daconfig.readsize = self.daconfig.flashsize // self.daconfig.pagesize * (
self.daconfig.pagesize + self.daconfig.sparesize)
self.show_progress("Read",0,100,display)
self.progress.show_progress("Read",0,100,display)
if filename != "":
with open(filename, "wb") as wf:
bytestoread = length
@ -1241,8 +1211,8 @@ class DALegacy(metaclass=LogBase):
checksum = unpack(">H", self.usbread(1)+self.usbread(1))[0]
self.debug("Checksum: %04X" % checksum)
self.usbwrite(self.Rsp.ACK)
self.show_progress("Read", length-bytestoread, length, display)
self.show_progress("Read", 100, 100, display)
self.progress.show_progress("Read", length-bytestoread, length, display)
self.progress.show_progress("Read", 100, 100, display)
return True
else:
buffer = bytearray()
@ -1256,6 +1226,6 @@ class DALegacy(metaclass=LogBase):
checksum = unpack(">H", self.usbread(2))[0]
self.debug("Checksum: %04X" % checksum)
self.usbwrite(self.Rsp.ACK)
self.show_progress("Read", length-bytestoread, length, display)
self.show_progress("Read", 100, 100, display)
self.progress.show_progress("Read", length-bytestoread, length, display)
self.progress.show_progress("Read", 100, 100, display)
return buffer

View file

@ -55,6 +55,16 @@ class DAloader(metaclass=LogBase):
return [True, partition]
return [False, fpartitions]
def get_partition_data(self, arguments, parttype=None):
fpartitions = []
data, guid_gpt = self.da.partition.get_gpt(int(arguments["--gpt-num-part-entries"]),
int(arguments["--gpt-part-entry-size"]),
int(arguments["--gpt-part-entry-start-lba"]), parttype)
if guid_gpt is None:
return [False, fpartitions]
else:
return guid_gpt.partentries
def get_gpt(self, arguments, parttype=None):
fpartitions = []
data, guid_gpt = self.da.partition.get_gpt(int(arguments["--gpt-num-part-entries"]),

View file

@ -7,10 +7,11 @@ import os
import hashlib
from binascii import hexlify
from struct import pack, unpack
from mtkclient.Library.utils import LogBase, print_progress, logsetup
from mtkclient.Library.utils import LogBase, progress, logsetup
from mtkclient.Library.error import ErrorHandler, ErrorCodes_XFlash
from mtkclient.Library.daconfig import EMMC_PartitionType, UFS_PartitionType, DaStorage
from mtkclient.Library.partition import Partition
from mtkclient.config.payloads import pathconfig
def find_binary(data, strf, pos=0):
t = strf.split(b".")
@ -42,6 +43,7 @@ def find_binary(data, strf, pos=0):
pre += 1
return -1
class NandExtension:
# uni=0, multi=1
cellusage = 0
@ -155,9 +157,6 @@ class DAXFlash(metaclass=LogBase):
self.debug = self.__logger.debug
self.error = self.__logger.error
self.warning = self.__logger.warning
self.progtime = 0
self.prog = 0
self.progpos = 0
self.mtk = mtk
self.loglevel = loglevel
self.sram = None
@ -179,6 +178,8 @@ class DAXFlash(metaclass=LogBase):
self.rword = self.mtk.port.rword
self.daconfig = daconfig
self.partition = Partition(self.mtk, self.readflash, self.read_pmt, loglevel)
self.progress = progress(self.daconfig.pagesize)
self.pathconfig = pathconfig()
def ack(self, rstatus=True):
try:
@ -186,14 +187,14 @@ class DAXFlash(metaclass=LogBase):
self.usbwrite(tmp)
data = pack("<I", 0)
self.usbwrite(data)
# time.sleep(0.0001)
if rstatus:
status=self.status()
status = self.status()
return status
return True
except:
return -1
def send(self, data, datatype=DataType.DT_PROTOCOL_FLOW):
if isinstance(data, int):
data = pack("<I", data)
@ -219,26 +220,21 @@ class DAXFlash(metaclass=LogBase):
return data
def status(self):
tmp = b""
status = None
bytestoread = 4 + 4 + 4
hdr = self.usbread(bytestoread)
magic, datatype, length = unpack("<III", hdr)
if magic != 0xFEEEEEEF:
self.error("Status error")
return -1
tmp = self.usbread(length)
try:
bytestoread=4+4+4
while bytestoread>0:
tmp+=self.usbread(bytestoread)
bytestoread-=len(tmp)
magic, datatype, length = unpack("<III", tmp)
bytestoread=length
tmp=b""
while bytestoread>0:
tmp+=self.usbread(length)
bytestoread -= len(tmp)
status = unpack("<"+str(length//4)+"I", tmp)[0]
status = unpack("<" + str(length // 4) + "I", tmp)[0]
if status == 0xFEEEEEEF:
return 0
except:
self.error("Failed to get status : "+hexlify(tmp).decode('utf-8'))
exit(1)
status = status
pass
return status
def read_pmt(self):
@ -250,7 +246,7 @@ class DAXFlash(metaclass=LogBase):
for param in params:
pkt = pack("<III", self.Cmd.MAGIC, self.DataType.DT_PROTOCOL_FLOW, len(param))
if self.usbwrite(pkt):
#time.sleep(0.05)
# time.sleep(0.05)
length = len(param)
pos = 0
while length > 0:
@ -264,38 +260,12 @@ class DAXFlash(metaclass=LogBase):
return True
else:
if status in ErrorCodes_XFlash:
errorstring=ErrorCodes_XFlash[status]
errorstring = ErrorCodes_XFlash[status]
self.error(f"Error on sending parameter: {errorstring}")
else:
self.error(f"Error on sending parameter, status {hex(status)}.")
return False
def show_progress(self, prefix, pos, total, display=True):
t0 = time.time()
if pos == 0:
self.prog = 0
self.progtime = time.time()
self.progpos = pos
prog = round(float(pos) / float(total) * float(100), 1)
if prog > self.prog:
if display:
tdiff = t0 - self.progtime
datasize = (pos - self.progpos) // 1024 // 1024
if datasize!=0:
try:
throughput = datasize // tdiff
except:
throughput = 0
else:
throughput = 0
print_progress(prog, 100, prefix='Progress:',
suffix=prefix + ' (Sector %d of %d) %0.2f MB/s' %
(pos // self.daconfig.pagesize,
total // self.daconfig.pagesize,
throughput), bar_length=50)
self.prog = prog
self.progpos = pos
self.progtime = t0
def send_devctrl(self, cmd, param=None, status=None):
if status is None:
@ -447,7 +417,7 @@ class DAXFlash(metaclass=LogBase):
return res
else:
if status in ErrorCodes_XFlash:
errorstring=ErrorCodes_XFlash[status]
errorstring = ErrorCodes_XFlash[status]
self.error(f"Error on getting connection agent: {errorstring}")
else:
self.error(f"Error on getting connection agent, status {hex(status)}.")
@ -594,7 +564,7 @@ class DAXFlash(metaclass=LogBase):
return sram, dram
return None, None
def get_emmc_info(self):
def get_emmc_info(self, display=True):
resp = self.send_devctrl(self.Cmd.GET_EMMC_INFO)
if self.status() == 0:
class EmmcInfo:
@ -624,7 +594,7 @@ class DAXFlash(metaclass=LogBase):
emmc.fwver = unpack("<Q", resp[pos:pos + 8])[0]
pos += 8
emmc.unknown = resp[pos:]
if emmc.type != 0:
if emmc.type != 0 and display:
self.info(f"EMMC FWVer: {hex(emmc.fwver)}")
self.info(f"EMMC CID: {hexlify(emmc.cid).decode('utf-8')}")
self.info(f"EMMC Boot1 Size: {hex(emmc.boot1_size)}")
@ -758,14 +728,14 @@ class DAXFlash(metaclass=LogBase):
return plen
else:
if status in ErrorCodes_XFlash:
errorstring=ErrorCodes_XFlash[status]
errorstring = ErrorCodes_XFlash[status]
self.error(f"Error on getting packet length: {errorstring}")
else:
self.error(f"Error on getting packet length, status {hex(status)}.")
return None
def cmd_write_data(self, addr, size, storage=DaStorage.MTK_DA_STORAGE_EMMC,
parttype=EMMC_PartitionType.MTK_DA_EMMC_PART_USER):
parttype=EMMC_PartitionType.MTK_DA_EMMC_PART_USER):
if self.send(self.Cmd.WRITE_DATA):
if self.status() == 0:
# storage: emmc:1,slc,nand,nor,ufs
@ -801,24 +771,10 @@ class DAXFlash(metaclass=LogBase):
return False
def readflash(self, addr, length, filename, parttype=None, display=True):
if self.daconfig.flashtype == "nor":
storage = DaStorage.MTK_DA_STORAGE_NOR
elif self.daconfig.flashtype == "nand":
storage = DaStorage.MTK_DA_STORAGE_NAND
elif self.daconfig.flashtype == "ufs":
storage = DaStorage.MTK_DA_STORAGE_UFS
if parttype == EMMC_PartitionType.MTK_DA_EMMC_PART_USER:
parttype = UFS_PartitionType.UFS_LU3
elif self.daconfig.flashtype == "sdc":
storage = DaStorage.MTK_DA_STORAGE_SDMMC
else:
storage = DaStorage.MTK_DA_STORAGE_EMMC
part_info = self.partitiontype_and_size(storage, parttype, length)
if not part_info:
partinfo = self.getstorage(parttype, length)
if not partinfo:
return False
storage, parttype, length = part_info
storage, parttype, length = partinfo
if self.cmd_read_data(addr=addr, size=length, storage=storage, parttype=parttype):
bytestoread = length
if filename != "":
@ -826,13 +782,16 @@ class DAXFlash(metaclass=LogBase):
with open(filename, "wb") as wf:
while bytestoread > 0:
magic, datatype, slength = unpack("<III", self.usbread(4 + 4 + 4))
tmp = self.usbread(slength)
if self.ack() != 0:
break
wf.write(tmp)
bytestoread -= len(tmp)
if display:
self.show_progress("Read", length-bytestoread, length, display)
if magic == 0xFEEEEEEF:
tmp = self.usbread(slength)
wf.write(tmp)
bytestoread -= len(tmp)
if self.ack() != 0:
return False
if display:
self.progress.show_progress("Read", length - bytestoread, length, display)
else:
return False
except Exception as err:
self.error("Couldn't write to " + filename + ". Error: " + str(err))
@ -846,7 +805,7 @@ class DAXFlash(metaclass=LogBase):
if self.ack() != 0:
break
if display:
self.show_progress("Read", length - bytestoread, length, display)
self.progress.show_progress("Read", length - bytestoread, length, display)
length -= len(tmp)
return buffer
return False
@ -859,7 +818,7 @@ class DAXFlash(metaclass=LogBase):
self.mtk.port.close()
return False
def writeflash(self, addr, length, filename, partitionname, offset=0, parttype=None, display=True):
def getstorage(self, parttype, length):
if self.daconfig.flashtype == "nor":
storage = DaStorage.MTK_DA_STORAGE_NOR
elif self.daconfig.flashtype == "nand":
@ -874,22 +833,25 @@ class DAXFlash(metaclass=LogBase):
storage = DaStorage.MTK_DA_STORAGE_EMMC
part_info = self.partitiontype_and_size(storage, parttype, length)
if not part_info:
return False
storage, parttype, length = part_info
return part_info
#self.send_devctrl(self.Cmd.START_DL_INFO)
def writeflash(self, addr, length, filename, partitionname, offset=0, parttype=None, display=True):
partinfo = self.getstorage(parttype, length)
if not partinfo:
return False
storage, parttype, length = partinfo
# self.send_devctrl(self.Cmd.START_DL_INFO)
plen = self.get_packet_length()
bytestowrite = length
write_packet_size = plen.write_packet_length
if self.cmd_write_data(addr,length,storage,parttype):
if self.cmd_write_data(addr, length, storage, parttype):
try:
with open(filename, "rb") as rf:
pos = 0
rf.seek(offset)
while bytestowrite > 0:
if display:
self.show_progress("Write", length - bytestowrite, length, display)
self.progress.show_progress("Write", length - bytestowrite, length, display)
dsize = min(write_packet_size, bytestowrite)
data = bytearray(rf.read(dsize))
checksum = sum(data) & 0xFFFF
@ -901,7 +863,7 @@ class DAXFlash(metaclass=LogBase):
pos += dsize
if self.status() == 0x0:
self.send_devctrl(self.Cmd.CC_OPTIONAL_DOWNLOAD_ACT)
self.show_progress("Write", length, length, display)
self.progress.show_progress("Write", length, length, display)
return True
except Exception as e:
self.error(str(e))
@ -976,13 +938,32 @@ class DAXFlash(metaclass=LogBase):
self.set_battery_opt(0x2)
self.set_checksum_level(0x0)
connagent = self.get_connection_agent()
emmc_info=self.get_emmc_info(False)
self.info("DRAM config needed for : " + hexlify(emmc_info.cid[:8]).decode('utf-8'))
# dev_fw_info=self.get_dev_fw_info()
# dramtype = self.get_dram_type()
stage = None
if connagent == b"brom":
stage = 2
if self.daconfig.emi is None:
self.warning("No preloader given. Operation may fail due to missing dram setup.")
self.info("No preloader given. Searching for preloader")
found = False
for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_loader_path(), 'Preloader')):
for file in files:
with open(os.path.join(root, file), "rb") as rf:
data = rf.read()
if emmc_info.cid[:8] in data:
preloader = os.path.join(root, file)
print("Detected preloader: " + preloader)
self.daconfig.extract_emi(preloader,False)
found = True
if not self.send_emi(self.daconfig.emi):
return False
break
if found:
break
if not found:
self.warning("No preloader given. Operation may fail due to missing dram setup.")
else:
if not self.send_emi(self.daconfig.emi):
return False
@ -1021,10 +1002,10 @@ class DAXFlash(metaclass=LogBase):
self.daconfig.flashsize = [self.ufs.lu0_size, self.ufs.lu1_size, self.ufs.lu2_size]
self.chipid = self.get_chip_id()
self.randomid = self.get_random_id()
#if self.get_da_stor_life_check() == 0x0:
# if self.get_da_stor_life_check() == 0x0:
cid = self.get_chip_id()
self.info("DA-CODE : 0x%X", (cid.hw_code<<4)+(cid.hw_code>>4))
open(os.path.join("logs", "hwcode.txt"), "w").write(hex(cid.hw_code))
self.info("DA-CODE : 0x%X", (cid.hw_code << 4) + (cid.hw_code >> 4))
open(os.path.join("logs", "hwcode.txt"), "w").write(hex(self.config.hwcode))
return True
else:
self.error("Error on booting to da (xflash)")

View file

@ -190,13 +190,13 @@ class Preloader(metaclass=LogBase):
self.setreg_disablewatchdogtimer(self.config.hwcode) # D4
if self.display:
self.info("HW code:\t\t\t" + hex(self.config.hwcode))
with open(os.path.join("logs", "hwcode"), "w") as wf:
with open(os.path.join("logs", "hwcode.txt"), "w") as wf:
wf.write(hex(self.config.hwcode))
self.config.target_config = self.get_target_config(self.display)
blver=self.get_blver()
meid = self.get_meid()
if len(meid) >= 16:
with open(os.path.join("logs", "meid"), "wb") as wf:
with open(os.path.join("logs", "meid.txt"), "wb") as wf:
wf.write(hexlify(meid))
if self.display:
if meid != b"":
@ -204,7 +204,7 @@ class Preloader(metaclass=LogBase):
if readsocid or self.config.chipconfig.socid_addr:
socid = self.get_socid()
if len(socid) >= 16:
with open(os.path.join("logs", "socid"), "wb") as wf:
with open(os.path.join("logs", "socid.txt"), "wb") as wf:
wf.write(hexlify(socid))
if self.display:
if socid != b"":

View file

@ -396,7 +396,7 @@ class usb_class(metaclass=LogBase):
return True
def read(self, maxlength=None, timeout=None):
if maxlength==None:
if maxlength is None:
maxlength=self.EP_IN.wMaxPacketSize
if self.loglevel == logging.DEBUG:
self.debug(inspect.currentframe().f_back.f_code.co_name + ":" + hex(maxlength))

View file

@ -11,6 +11,7 @@ import shutil
import stat
import colorama
import copy
import time
try:
from capstone import *
@ -21,10 +22,49 @@ try:
except ImportError:
print("Keystone library is missing (optional).")
from struct import unpack, pack
class progress:
def __init__(self, pagesize):
self.progtime = 0
self.prog = 0
self.progpos = 0
self.pagesize = pagesize
def show_progress(self, prefix, pos, total, display=True):
t0 = time.time()
prog = round(float(pos) / float(total) * float(100), 2)
if prog == 0:
self.prog = 0
self.progtime = time.time()
self.progpos = pos
print_progress(prog, 100, prefix='Progress:',
suffix=prefix + ' (Sector %d of %d) %0.2f MB/s' %
(pos // self.pagesize,
total // self.pagesize,
0), bar_length=50)
if prog > self.prog:
if display:
tdiff = t0 - self.progtime
datasize = (pos - self.progpos) / 1024 / 1024
if datasize != 0 and tdiff != 0:
try:
throughput = datasize / tdiff
except:
throughput = 0
else:
throughput = 0
print_progress(prog, 100, prefix='Progress:',
suffix=prefix + ' (Sector %d of %d) %0.2f MB/s' %
(pos // self.pagesize,
total // self.pagesize,
throughput), bar_length=50)
self.prog = prog
self.progpos = pos
self.progtime = t0
class structhelper:
pos = 0
@ -53,7 +93,7 @@ class structhelper:
return dat
def shorts(self, shorts):
dat = unpack("<" + str(shorts) + "H", self.data[self.pos:self.pos + 2*shorts])
dat = unpack("<" + str(shorts) + "H", self.data[self.pos:self.pos + 2 * shorts])
self.pos += 2 * shorts
return dat
@ -74,6 +114,7 @@ class structhelper:
def seek(self, pos):
self.pos = pos
def do_tcp_server(client, arguments, handler):
def tcpprint(arg):
if isinstance(arg, bytes) or isinstance(arg, bytearray):
@ -241,9 +282,11 @@ class ColorFormatter(logging.Formatter):
# now we can let standart formatting take care of the rest
return super(ColorFormatter, self).format(new_record, *args, **kwargs)
def revdword(value):
return unpack(">I", pack("<I", value))[0]
def logsetup(self, logger, loglevel):
self.info = logger.info
self.debug = logger.debug
@ -259,6 +302,7 @@ def logsetup(self, logger, loglevel):
self.loglevel = loglevel
return logger
class LogBase(type):
debuglevel = logging.root.level

View file

@ -149,7 +149,7 @@ hwconfig = {
da_payload_addr=0x2008000,
pl_payload_addr=0x2008000,
# no gcpu_base =0x10210000,
# sej_base =0x1000A000, # hacc
sej_base =0x1000A000, # hacc
# no dxcc
# no cqdma_base
# no ap_dma_mem
@ -901,7 +901,6 @@ hwconfig = {
cqdma_base=0x11B30000,
ap_dma_mem=0x11000000 + 0x1A0, # AP_DMA_I2C_2_RX_MEM_ADDR
# no dxcc
# no dxcc
sej_base=0x1000A000,
blacklist=[(0x00102870, 0x0),(0x00107070, 0x0)],
blacklist_count=0x0000000A,
@ -924,8 +923,8 @@ hwconfig = {
da_payload_addr=0x201000, #
pl_payload_addr=0x40200000,
# gcpu_base=0x10050000, #
# dxcc_base=0x10210000, #
# sej_base=0x1000a000, # hacc
dxcc_base=0x10210000,
sej_base=0x1000a000, # hacc
# cqdma_base=0x10212000, #
# ap_dma_mem=0x11000a80 + 0x1a0, # todo check
blacklist=[(0x00102844, 0x0),(0x00106B54, 0x0)],
@ -995,7 +994,8 @@ hwconfig = {
# brom_payload_addr
# da_payload_addr
# gcpu_base
# sej_base
dxcc_base=0x10210000,
sej_base=0x1000a000, # hacc
# cqdma_base
# ap_dma_mem
# blacklist
@ -1036,8 +1036,8 @@ hwconfig = {
da_payload_addr=0x201000,
pl_payload_addr=0x40200000,
#gcpu_base=0x10050000,
#dxcc_base=0x10210000,
#sej_base=0x1000a000, # hacc
dxcc_base=0x10210000,
sej_base=0x1000a000, # hacc
#cqdma_base=0x10212000,
#ap_dma_mem=0x11000a80 + 0x1a0, # todo check
blacklist=[(0x102848, 0x0), (0x00106B60, 0x0)],
@ -1050,7 +1050,7 @@ hwconfig = {
socid_addr=0x102BA8,
damode=damodes.XFLASH,
dacode=0x6893,
name="MT6893/MT6891Z",
name="MT6893",
description="Dimensity 1200",
loader="mt6893_payload.bin"),
# Dimensity 1100 - MT6891 Realme Q3 Pro

View file

@ -8,7 +8,7 @@ class pathconfig:
self.scriptpath = os.path.dirname(curscript)
def get_loader_path(self):
return os.path.join(self.scriptpath,"..","Loader")
return os.path.abspath(os.path.join(self.scriptpath,"..","Loader"))
def get_payloads_path(self):
return os.path.join(self.scriptpath,"..","payloads")
return os.path.abspath(os.path.join(self.scriptpath,"..","payloads"))

View file

@ -6,4 +6,5 @@ default_ids = [
[0x0E8D, 0x20FF, -1], # MTK Preloader
[0x1004, 0x6000, 2], # LG Preloader
[0x22d9, 0x0006, 2], # OPPO Preloader
[0x1a86, 0x7523, 0]
]