mirror of
https://github.com/bkerler/mtkclient.git
synced 2024-11-14 19:25:05 -05:00
GUI preparation, restructure
This commit is contained in:
parent
5c4c6f8c1a
commit
5b76cc84d1
8 changed files with 912 additions and 791 deletions
|
@ -14,6 +14,15 @@ try:
|
|||
except:
|
||||
from utils import LogBase, structhelper
|
||||
|
||||
class gpt_settings:
|
||||
gpt_num_part_entries = 0
|
||||
gpt_part_entry_size = 0
|
||||
gpt_part_entry_start_lba = 0
|
||||
|
||||
def __init__(self, gpt_num_part_entries: str, gpt_part_entry_size: str, gpt_part_entry_start_lba: str):
|
||||
self.gpt_num_part_entries = int(gpt_num_part_entries)
|
||||
self.gpt_part_entry_size = int(gpt_part_entry_size)
|
||||
self.gpt_part_entry_start_lba = int(gpt_part_entry_start_lba)
|
||||
|
||||
class gpt(metaclass=LogBase):
|
||||
class gpt_header:
|
||||
|
|
|
@ -126,7 +126,7 @@ class legacyext(metaclass=LogBase):
|
|||
return False
|
||||
hwc = self.cryptosetup()
|
||||
sc_org = seccfg(hwc)
|
||||
data, guid_gpt = self.legacy.partition.get_gpt(0, 0, 0, "user")
|
||||
data, guid_gpt = self.legacy.partition.get_gpt(self.mtk.config.gpt_settings, "user")
|
||||
seccfg_data = None
|
||||
partition = None
|
||||
for rpartition in guid_gpt.partentries:
|
||||
|
|
650
mtkclient/Library/mtk_da_cmd.py
Normal file
650
mtkclient/Library/mtk_da_cmd.py
Normal file
|
@ -0,0 +1,650 @@
|
|||
import os
|
||||
import time
|
||||
import sys
|
||||
import logging
|
||||
from struct import pack, unpack
|
||||
from binascii import hexlify
|
||||
from mtkclient.Library.utils import LogBase, logsetup, getint
|
||||
from mtkclient.config.payloads import pathconfig
|
||||
from mtkclient.Library.error import ErrorHandler
|
||||
|
||||
|
||||
class DA_handler(metaclass=LogBase):
|
||||
def __init__(self, mtk, loglevel=logging.INFO):
|
||||
self.__logger = self.__logger
|
||||
self.info = self.__logger.info
|
||||
self.debug = self.__logger.debug
|
||||
self.error = self.__logger.error
|
||||
self.warning = self.__logger.warning
|
||||
self.config = mtk.config
|
||||
self.loader = mtk.config.loader
|
||||
self.vid = mtk.config.vid
|
||||
self.pid = mtk.config.pid
|
||||
self.interface = mtk.config.interface
|
||||
self.pathconfig = pathconfig()
|
||||
self.__logger = logsetup(self, self.__logger, loglevel)
|
||||
self.eh = ErrorHandler()
|
||||
self.mtk = mtk
|
||||
|
||||
def close(self):
|
||||
sys.exit(0)
|
||||
|
||||
def dump_preloader_ram(self):
|
||||
try:
|
||||
data = b"".join([pack("<I", val) for val in self.mtk.preloader.read32(0x200000, 0x10000 // 4)])
|
||||
idx = data.find(b"\x4D\x4D\x4D\x01\x38\x00\x00\x00")
|
||||
if idx != -1:
|
||||
data = data[idx:]
|
||||
length = unpack("<I", data[0x20:0x24])[0]
|
||||
time.sleep(0.05)
|
||||
data = b"".join([pack("<I", val) for val in self.mtk.preloader.read32(0x200000 + idx, length + 4 // 4)])
|
||||
preloader = data[:length]
|
||||
idx = data.find(b"MTK_BLOADER_INFO")
|
||||
if idx != -1:
|
||||
filename = data[idx + 0x1B:idx + 0x1B + 0x30].rstrip(b"\x00").decode('utf-8')
|
||||
if preloader is not None:
|
||||
pfilename = os.path.join(self.mtk.pathconfig.get_loader_path(), "Preloader", filename)
|
||||
if not os.path.exists(pfilename):
|
||||
with open(pfilename, "wb") as wf:
|
||||
wf.write(preloader)
|
||||
print(f"Successfully extracted preloader for this device to: {pfilename}")
|
||||
return preloader
|
||||
except Exception as err:
|
||||
self.error(str(err))
|
||||
return None
|
||||
|
||||
def configure_da(self, mtk, preloader):
|
||||
mtk.port.cdc.connected = mtk.port.cdc.connect()
|
||||
if mtk.port.cdc.connected and os.path.exists(".state"):
|
||||
info = mtk.daloader.reinit()
|
||||
else:
|
||||
if mtk.preloader.init():
|
||||
if mtk.config.target_config["daa"]:
|
||||
mtk = mtk.bypass_security()
|
||||
self.info("Device is protected.")
|
||||
if mtk is not None:
|
||||
if mtk.config.is_brom:
|
||||
self.info("Device is in BROM mode. Trying to dump preloader.")
|
||||
if preloader is None:
|
||||
preloader = self.dump_preloader_ram()
|
||||
else:
|
||||
self.info("Device is unprotected.")
|
||||
if mtk.config.is_brom:
|
||||
mtk = mtk.bypass_security() # Needed for dumping preloader
|
||||
if preloader is None:
|
||||
self.warning(
|
||||
"Device is in BROM mode. No preloader given, trying to dump preloader from ram.")
|
||||
preloader = self.dump_preloader_ram()
|
||||
if preloader is None:
|
||||
self.error("Failed to dump preloader from ram.")
|
||||
if not mtk.daloader.upload_da(preloader=preloader):
|
||||
self.error("Error uploading da")
|
||||
return False
|
||||
else:
|
||||
mtk.daloader.writestate()
|
||||
else:
|
||||
return False
|
||||
|
||||
def da_gpt(self, directory:str):
|
||||
if directory is None:
|
||||
directory = ""
|
||||
|
||||
sfilename = os.path.join(directory, f"gpt_main.bin")
|
||||
data, guid_gpt = self.mtk.daloader.get_gpt()
|
||||
if guid_gpt is None:
|
||||
self.error("Error reading gpt")
|
||||
self.close()
|
||||
else:
|
||||
with open(sfilename, "wb") as wf:
|
||||
wf.write(data)
|
||||
|
||||
print(f"Dumped GPT from to {sfilename}")
|
||||
sfilename = os.path.join(directory, f"gpt_backup.bin")
|
||||
with open(sfilename, "wb") as wf:
|
||||
wf.write(data[self.mtk.daloader.daconfig.pagesize:])
|
||||
print(f"Dumped Backup GPT to {sfilename}")
|
||||
|
||||
def da_read(self, partitionname, parttype, filename):
|
||||
filenames = filename.split(",")
|
||||
partitions = partitionname.split(",")
|
||||
if len(partitions) != len(filenames):
|
||||
self.error("You need to gives as many filenames as given partitions.")
|
||||
self.close()
|
||||
if parttype == "user" or parttype is None:
|
||||
i = 0
|
||||
countDump = 0
|
||||
self.info("Requesting available partitions ....")
|
||||
gpttable = self.mtk.daloader.get_partition_data(parttype=parttype)
|
||||
for partition in partitions:
|
||||
partfilename = filenames[i]
|
||||
i += 1
|
||||
if partition == "gpt":
|
||||
self.mtk.daloader.readflash(addr=0,
|
||||
length=0x16000,
|
||||
filename=partfilename, parttype=parttype)
|
||||
continue
|
||||
else:
|
||||
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 self.mtk.daloader.readflash(addr=rpartition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=rpartition.sectors * self.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}.")
|
||||
countDump += 1
|
||||
else:
|
||||
self.info(f"Failed to dump sector {str(rpartition.sector)} with sector count " +
|
||||
f"{str(rpartition.sectors)} as {partfilename}.")
|
||||
countDump += 1
|
||||
else:
|
||||
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
|
||||
for rpartition in gpttable:
|
||||
self.info(rpartition.name)
|
||||
if countDump > 1 and countDump == len(filenames):
|
||||
self.info(f"All partitions were dumped")
|
||||
elif countDump > 1 and countDump != len(filenames):
|
||||
self.info(f"Failed to dump some partitions")
|
||||
else:
|
||||
i = 0
|
||||
for partfilename in filenames:
|
||||
pos = 0
|
||||
if self.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
|
||||
|
||||
def da_rl(self, directory, parttype, skip):
|
||||
if not os.path.exists(directory):
|
||||
os.mkdir(directory)
|
||||
data, guid_gpt = self.mtk.daloader.get_gpt(parttype=parttype)
|
||||
if guid_gpt is None:
|
||||
self.error("Error reading gpt")
|
||||
else:
|
||||
storedir = directory
|
||||
if not os.path.exists(storedir):
|
||||
os.mkdir(storedir)
|
||||
sfilename = os.path.join(storedir, f"gpt_main.bin")
|
||||
with open(sfilename, "wb") as wf:
|
||||
wf.write(data)
|
||||
|
||||
sfilename = os.path.join(storedir, f"gpt_backup.bin")
|
||||
with open(sfilename, "wb") as wf:
|
||||
wf.write(data[self.mtk.daloader.daconfig.pagesize * 2:])
|
||||
|
||||
countGPT = 0
|
||||
for partition in guid_gpt.partentries:
|
||||
partitionname = partition.name
|
||||
if partition.name in skip:
|
||||
continue
|
||||
filename = os.path.join(storedir, partitionname + ".bin")
|
||||
self.info(
|
||||
f"Dumping partition {str(partition.name)} with sector count {str(partition.sectors)} " +
|
||||
f"as {filename}.")
|
||||
|
||||
if self.mtk.daloader.readflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=partition.sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
filename=filename,
|
||||
parttype=parttype):
|
||||
|
||||
countGPT += 1
|
||||
self.info(f"Dumped partition {str(partition.name)} as {str(filename)}.")
|
||||
else:
|
||||
countGPT -= 1
|
||||
self.error(f"Failed to dump partition {str(partition.name)} as {str(filename)}.")
|
||||
|
||||
partitionsForRead = len(guid_gpt.partentries) - len(skip)
|
||||
if countGPT == partitionsForRead:
|
||||
self.info(f"All Dumped partitions success.")
|
||||
else:
|
||||
self.error(f"Failed to dump all partitions")
|
||||
|
||||
def da_rf(self, filename, parttype):
|
||||
if self.mtk.daloader.daconfig.flashtype == "ufs":
|
||||
if parttype == "lu0":
|
||||
length = self.mtk.daloader.daconfig.flashsize[0]
|
||||
elif parttype == "lu1":
|
||||
length = self.mtk.daloader.daconfig.flashsize[1]
|
||||
elif parttype == "lu2":
|
||||
length = self.mtk.daloader.daconfig.flashsize[2]
|
||||
else:
|
||||
length = self.mtk.daloader.daconfig.flashsize[0]
|
||||
else:
|
||||
length = self.mtk.daloader.daconfig.flashsize
|
||||
print(f"Dumping sector 0 with flash size {hex(length)} as {filename}.")
|
||||
if self.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}.")
|
||||
|
||||
def da_rs(self, start: int, sectors: int, filename: str, parttype: str):
|
||||
return self.mtk.daloader.readflash(addr=start * self.mtk.daloader.daconfig.pagesize,
|
||||
length=sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
filename=filename, parttype=parttype)
|
||||
|
||||
def da_ro(self, start: int, length: int, filename: str, parttype: str):
|
||||
return self.mtk.daloader.readflash(addr=start,
|
||||
length=length,
|
||||
filename=filename, parttype=parttype)
|
||||
|
||||
def da_footer(self, filename: str):
|
||||
data, guid_gpt = self.mtk.daloader.get_gpt()
|
||||
if guid_gpt is None:
|
||||
self.error("Error reading gpt")
|
||||
return
|
||||
else:
|
||||
pnames = ["userdata2", "metadata", "userdata", "reserved1", "reserved2", "reserved3"]
|
||||
for partition in guid_gpt.partentries:
|
||||
if partition.name in pnames:
|
||||
print(f"Detected partition: {partition.name}")
|
||||
if partition.name in ["userdata2", "userdata"]:
|
||||
data = self.mtk.daloader.readflash(
|
||||
addr=(partition.sector + partition.sectors) * self.mtk.daloader.daconfig.pagesize - 0x4000,
|
||||
length=0x4000, filename="", parttype="user", display=False)
|
||||
else:
|
||||
data = self.mtk.daloader.readflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=0x4000, filename="", parttype="user",
|
||||
display=False)
|
||||
if data == b"":
|
||||
continue
|
||||
val = unpack("<I", data[:4])[0]
|
||||
if (val & 0xFFFFFFF0) == 0xD0B5B1C0:
|
||||
with open(filename, "wb") as wf:
|
||||
wf.write(data)
|
||||
print(f"Dumped footer from {partition.name} as {filename}.")
|
||||
return
|
||||
self.error(f"Error: Couldn't detect footer partition.")
|
||||
|
||||
def da_write(self, parttype: str, filenames: list, partitions: list):
|
||||
if len(partitions) != len(filenames):
|
||||
self.error("You need to gives as many filenames as given partitions.")
|
||||
self.close()
|
||||
exit(0)
|
||||
if parttype == "user" or parttype is None:
|
||||
i = 0
|
||||
for partition in partitions:
|
||||
partfilename = filenames[i]
|
||||
i += 1
|
||||
if partition == "gpt":
|
||||
self.mtk.daloader.writeflash(addr=0,
|
||||
length=os.stat(partfilename).st_size,
|
||||
filename=partfilename,
|
||||
parttype=parttype)
|
||||
continue
|
||||
res = self.mtk.daloader.detect_partition(partition, parttype)
|
||||
if res[0]:
|
||||
rpartition = res[1]
|
||||
if self.mtk.daloader.writeflash(addr=rpartition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=rpartition.sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
filename=partfilename,
|
||||
parttype=parttype):
|
||||
print(
|
||||
f"Wrote {partfilename} to sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
else:
|
||||
print(
|
||||
f"Failed to write {partfilename} to sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
else:
|
||||
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
|
||||
for rpartition in res[1]:
|
||||
self.info(rpartition.name)
|
||||
else:
|
||||
pos = 0
|
||||
for partfilename in filenames:
|
||||
size = os.stat(partfilename).st_size
|
||||
if self.mtk.daloader.writeflash(addr=pos, length=size, filename=partfilename,
|
||||
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)}.")
|
||||
psize = size // 0x200 * 0x200
|
||||
if size % 0x200 != 0:
|
||||
psize += 0x200
|
||||
pos += psize
|
||||
|
||||
def da_wl(self, parttype: str, directory: str):
|
||||
filenames = []
|
||||
for dirName, subdirList, fileList in os.walk(directory):
|
||||
for fname in fileList:
|
||||
filenames.append(os.path.join(dirName, fname))
|
||||
|
||||
if parttype == "user" or parttype is None:
|
||||
i = 0
|
||||
for partfilename in filenames:
|
||||
partition = os.path.basename(partfilename)
|
||||
partition = os.path.splitext(partition)[0]
|
||||
i += 1
|
||||
if partition == "gpt":
|
||||
self.info(f"Writing partition {partition}")
|
||||
if self.mtk.daloader.writeflash(addr=0,
|
||||
length=os.stat(partfilename).st_size,
|
||||
filename=partfilename,
|
||||
parttype=parttype):
|
||||
print(f"Wrote {partition} to sector {str(0)}")
|
||||
else:
|
||||
print(f"Failed to write {partition} to sector {str(0)}")
|
||||
continue
|
||||
res = self.mtk.daloader.detect_partition(partition, parttype)
|
||||
if res[0]:
|
||||
rpartition = res[1]
|
||||
if self.mtk.daloader.writeflash(addr=rpartition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=rpartition.sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
filename=partfilename,
|
||||
parttype=parttype):
|
||||
print(
|
||||
f"Wrote {partfilename} to sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
else:
|
||||
print(
|
||||
f"Failed to write {partfilename} to sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
else:
|
||||
self.error(f"Error: Couldn't detect partition: {partition}\n, skipping")
|
||||
else:
|
||||
pos = 0
|
||||
for partfilename in filenames:
|
||||
size = os.stat(partfilename).st_size
|
||||
partition = os.path.basename(partfilename)
|
||||
partition = os.path.splitext(partition)[0]
|
||||
self.info(f"Writing filename {partfilename}")
|
||||
if self.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:
|
||||
print(f"Failed to write {partfilename} to sector {str(pos // 0x200)} with " +
|
||||
f"sector count {str(size)}.")
|
||||
psize = size // 0x200 * 0x200
|
||||
if size % 0x200 != 0:
|
||||
psize += 0x200
|
||||
pos += psize
|
||||
|
||||
def da_wo(self, start: int, length: int, filename: str, parttype: str):
|
||||
return self.mtk.daloader.writeflash(addr=start,
|
||||
length=length,
|
||||
filename=filename,
|
||||
parttype=parttype)
|
||||
|
||||
def da_erase(self, partitions: list, parttype: str):
|
||||
countFP = 0
|
||||
if parttype == "user" or parttype is None:
|
||||
i = 0
|
||||
for partition in partitions:
|
||||
i += 1
|
||||
res = self.mtk.daloader.detect_partition(partition, parttype)
|
||||
if res[0]:
|
||||
rpartition = res[1]
|
||||
if self.mtk.daloader.formatflash(addr=rpartition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=rpartition.sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
partitionname=partition, parttype=parttype):
|
||||
print(
|
||||
f"Formatted sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
countFP += 1
|
||||
else:
|
||||
print(
|
||||
f"Failed to format sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
countFP -= 1
|
||||
else:
|
||||
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
|
||||
for rpartition in res[1]:
|
||||
self.info(rpartition.name)
|
||||
if countFP == len(partitions) and countFP > 1:
|
||||
print(f"All partitions formatted.")
|
||||
elif countFP != len(partitions) and countFP > 1:
|
||||
print(f"Failed to format all partitions.")
|
||||
|
||||
def da_es(self, partitions: list, parttype: str, sectors: int):
|
||||
if parttype == "user" or parttype is None:
|
||||
i = 0
|
||||
for partition in partitions:
|
||||
i += 1
|
||||
res = self.mtk.daloader.detect_partition(partition, parttype)
|
||||
if res[0]:
|
||||
rpartition = res[1]
|
||||
rsectors = min(sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
rpartition.sectors * self.mtk.daloader.daconfig.pagesize)
|
||||
if sectors > rsectors:
|
||||
self.error(f"Partition {partition} only has {rsectors}, you were using {sectors}. " +
|
||||
f"Aborting")
|
||||
continue
|
||||
wipedata = b"\x00" * 0x200000
|
||||
error = False
|
||||
sector = rpartition.sector
|
||||
while sectors:
|
||||
sectorsize = sectors * self.mtk.daloader.daconfig.pagesize
|
||||
wsize = min(sectorsize, 0x200000)
|
||||
if self.mtk.daloader.writeflash(addr=sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=wsize,
|
||||
filename=None,
|
||||
wdata=wipedata[:wsize],
|
||||
parttype=parttype):
|
||||
print(
|
||||
f"Failed to format sector {str(sector)} with " +
|
||||
f"sector count {str(sectors)}.")
|
||||
error = True
|
||||
break
|
||||
sectors -= (wsize // self.mtk.daloader.daconfig.pagesize)
|
||||
sector += (wsize // self.mtk.daloader.daconfig.pagesize)
|
||||
if not error:
|
||||
print(
|
||||
f"Formatted sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(sectors)}.")
|
||||
else:
|
||||
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
|
||||
for rpartition in res[1]:
|
||||
self.info(rpartition.name)
|
||||
else:
|
||||
pos = 0
|
||||
for partitionname in partitions:
|
||||
self.mtk.daloader.formatflash(addr=pos, length=0xF000000, partitionname=partitionname,
|
||||
parttype=parttype,
|
||||
display=True)
|
||||
print(f"Formatted sector {str(pos // 0x200)}")
|
||||
|
||||
def da_wf(self, filenames: list, parttype: str):
|
||||
pos = 0
|
||||
for partfilename in filenames:
|
||||
size = os.stat(partfilename).st_size // 0x200 * 0x200
|
||||
if self.mtk.daloader.writeflash(addr=pos,
|
||||
length=size,
|
||||
filename=partfilename,
|
||||
parttype=parttype):
|
||||
print(f"Wrote {partfilename} to sector {str(pos // 0x200)} with " +
|
||||
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)}.")
|
||||
|
||||
def da_peek(self, addr: int, length: int, filename: str):
|
||||
data = self.mtk.daloader.peek(addr=addr, length=length)
|
||||
if data != b"":
|
||||
if filename is not None:
|
||||
open(filename, "wb").write(data)
|
||||
self.info(f"Successfully wrote data from {hex(addr)}, length {hex(length)} to {filename}")
|
||||
else:
|
||||
self.info(
|
||||
f"Data read from {hex(addr)}, length: {hex(length)}:\n{hexlify(data).decode('utf-8')}\n")
|
||||
|
||||
def da_poke(self, addr: int, data: str, filename: str):
|
||||
if filename is not None:
|
||||
if os.path.exists(filename):
|
||||
data = open(filename, "rb").read()
|
||||
else:
|
||||
if "0x" in data:
|
||||
data = pack("<I", int(data, 16))
|
||||
else:
|
||||
data = bytes.fromhex(data)
|
||||
if self.mtk.daloader.poke(addr=addr, data=data):
|
||||
self.info(f"Successfully wrote data to {hex(addr)}, length {hex(len(data))}")
|
||||
|
||||
def handle_da_cmds(self, mtk, cmd: str, args):
|
||||
try:
|
||||
preloader = args.preloader
|
||||
except:
|
||||
preloader = None
|
||||
self.configure_da(mtk, preloader)
|
||||
|
||||
if cmd == "gpt":
|
||||
directory = args.directory
|
||||
self.da_gpt(directory=directory)
|
||||
self.close()
|
||||
elif cmd == "printgpt":
|
||||
data, guid_gpt = mtk.daloader.get_gpt()
|
||||
if guid_gpt is None:
|
||||
self.error("Error reading gpt")
|
||||
else:
|
||||
guid_gpt.print()
|
||||
self.close()
|
||||
elif cmd == "r":
|
||||
partitionname = args.partitionname
|
||||
parttype = args.parttype
|
||||
filename = args.filename
|
||||
self.da_read(partitionname=partitionname, parttype=parttype, filename=filename)
|
||||
self.close()
|
||||
elif cmd == "rl":
|
||||
directory = args.directory
|
||||
parttype = args.parttype
|
||||
if args.skip:
|
||||
skip = args.skip.split(",")
|
||||
else:
|
||||
skip = []
|
||||
self.da_rl(directory=directory, parttype=parttype, skip=skip)
|
||||
self.close()
|
||||
elif cmd == "rf":
|
||||
filename = args.filename
|
||||
parttype = args.parttype
|
||||
self.da_rf(filename=filename, parttype=parttype)
|
||||
self.close()
|
||||
elif cmd == "rs":
|
||||
start = getint(args.startsector)
|
||||
sectors = getint(args.sectors)
|
||||
filename = args.filename
|
||||
parttype = args.parttype
|
||||
if self.da_rs(start=start, sectors=sectors, 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}.")
|
||||
self.close()
|
||||
elif cmd == "ro":
|
||||
start = getint(args.offset)
|
||||
length = getint(args.length)
|
||||
filename = args.filename
|
||||
parttype = args.parttype
|
||||
if self.da_ro(start=start, length=length, filename=filename, parttype=parttype):
|
||||
print(f"Dumped offset {hex(start)} with length {hex(length)} as {filename}.")
|
||||
else:
|
||||
print(f"Failed to dump offset {hex(start)} with length {hex(length)} as {filename}.")
|
||||
self.close()
|
||||
elif cmd == "footer":
|
||||
filename = args.filename
|
||||
self.da_footer(filename=filename)
|
||||
self.close()
|
||||
elif cmd == "w":
|
||||
partitionname = args.partitionname
|
||||
filename = args.filename
|
||||
parttype = args.parttype
|
||||
filenames = filename.split(",")
|
||||
partitions = partitionname.split(",")
|
||||
self.da_write(parttype=parttype, filenames=filenames, partitions=partitions)
|
||||
self.close()
|
||||
elif cmd == "wl":
|
||||
directory = args.directory
|
||||
parttype = args.parttype
|
||||
self.da_wl(directory=directory, parttype=parttype)
|
||||
self.close()
|
||||
elif cmd == "wo":
|
||||
start = getint(args.offset)
|
||||
length = getint(args.length)
|
||||
filename = args.filename
|
||||
parttype = args.parttype
|
||||
if filename is None:
|
||||
self.error("No filename given to write to flash")
|
||||
self.close()
|
||||
return
|
||||
if not os.path.exists(filename):
|
||||
self.error(f"Filename {filename} to write doesn't exist")
|
||||
self.close()
|
||||
return
|
||||
self.info(f"Writing offset {hex(start)} with length {hex(length)}")
|
||||
|
||||
if self.da_wo(start=start, length=length, filename=filename, parttype=parttype):
|
||||
print(f"Wrote {filename} to offset {hex(start)} with " +
|
||||
f"length {hex(length)}.")
|
||||
else:
|
||||
print(f"Failed to write {filename} to offset {hex(start)} with " +
|
||||
f"length {hex(length)}.")
|
||||
self.close()
|
||||
elif cmd == "wf":
|
||||
filename = args.filename
|
||||
parttype = args.parttype
|
||||
filenames = filename.split(",")
|
||||
self.da_wf(filenames=filenames, parttype=parttype)
|
||||
self.close()
|
||||
elif cmd == "e":
|
||||
partitionname = args.partitionname
|
||||
parttype = args.parttype
|
||||
partitions = partitionname.split(",")
|
||||
self.da_erase(partitions=partitions, parttype=parttype)
|
||||
self.close()
|
||||
elif cmd == "es":
|
||||
partitionname = args.partitionname
|
||||
parttype = args.parttype
|
||||
sectors = getint(args.sectors)
|
||||
if args.sectors is None:
|
||||
self.error("Sector count is missing. Usage: es [partname] [sector count]")
|
||||
self.close()
|
||||
partitions = partitionname.split(",")
|
||||
self.da_es(partitions=partitions, parttype=parttype, sectors=sectors)
|
||||
self.close()
|
||||
elif cmd == "reset":
|
||||
if os.path.exists(".state"):
|
||||
os.remove(".state")
|
||||
mtk.daloader.close()
|
||||
self.close()
|
||||
print("Reset command was sent. Disconnect usb cable to power off.")
|
||||
elif cmd == "da":
|
||||
subcmd = args.subcmd
|
||||
if subcmd is None:
|
||||
print("Available da cmds are: [peek, poke, generatekeys, seccfg, rpmb, meta]")
|
||||
return
|
||||
if subcmd == "peek":
|
||||
addr = getint(args.address)
|
||||
length = getint(args.length)
|
||||
filename = args.filename
|
||||
self.da_peek(addr=addr, length=length, filename=filename)
|
||||
elif subcmd == "poke":
|
||||
addr = getint(args.address)
|
||||
filename = args.filename
|
||||
data = args.data
|
||||
self.da_poke(addr=addr, data=data, filename=filename)
|
||||
elif subcmd == "generatekeys":
|
||||
mtk.daloader.keys()
|
||||
elif subcmd == "seccfg":
|
||||
mtk.daloader.seccfg(args.flag)
|
||||
elif subcmd == "rpmb":
|
||||
rpmb_subcmd = args.rpmb_subcmd
|
||||
if rpmb_subcmd is None:
|
||||
print('Available da xflash rpmb cmds are: [r w]')
|
||||
if rpmb_subcmd == "r":
|
||||
mtk.daloader.read_rpmb(args.filename)
|
||||
elif rpmb_subcmd == "w":
|
||||
mtk.daloader.write_rpmb(args.filename)
|
||||
elif subcmd == "meta":
|
||||
metamode = args.metamode
|
||||
if metamode is None:
|
||||
print("metamode is needed [usb,uart,off]!")
|
||||
else:
|
||||
mtk.daloader.setmetamode(metamode)
|
||||
self.close()
|
|
@ -14,6 +14,7 @@ from mtkclient.config.brom_config import damodes
|
|||
from mtkclient.Library.xflash_ext import xflashext
|
||||
from mtkclient.Library.legacy_ext import legacyext
|
||||
|
||||
|
||||
class DAloader(metaclass=LogBase):
|
||||
def __init__(self, mtk, loglevel=logging.INFO):
|
||||
self.__logger = logsetup(self, self.__logger, loglevel)
|
||||
|
@ -149,11 +150,9 @@ class DAloader(metaclass=LogBase):
|
|||
self.error("Device is not in xflash mode, cannot run meta cmd.")
|
||||
return False
|
||||
|
||||
def detect_partition(self, arguments, partitionname, parttype=None):
|
||||
def detect_partition(self, partitionname, 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)
|
||||
data, guid_gpt = self.da.partition.get_gpt(self.mtk.config.gpt_settings, parttype)
|
||||
if guid_gpt is None:
|
||||
return [False, fpartitions]
|
||||
else:
|
||||
|
@ -163,21 +162,17 @@ class DAloader(metaclass=LogBase):
|
|||
return [True, partition]
|
||||
return [False, fpartitions]
|
||||
|
||||
def get_partition_data(self, arguments, parttype=None):
|
||||
def get_partition_data(self, 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)
|
||||
data, guid_gpt = self.da.partition.get_gpt(self.mtk.config.gpt_settings, parttype)
|
||||
if guid_gpt is None:
|
||||
return [False, fpartitions]
|
||||
else:
|
||||
return guid_gpt.partentries
|
||||
|
||||
def get_gpt(self, arguments, parttype=None):
|
||||
def get_gpt(self, 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)
|
||||
data, guid_gpt = self.da.partition.get_gpt(self.mtk.config.gpt_settings, parttype)
|
||||
if guid_gpt is None:
|
||||
return [False, fpartitions]
|
||||
return [data, guid_gpt]
|
||||
|
|
|
@ -14,7 +14,7 @@ class Partition(metaclass=LogBase):
|
|||
self.readflash = readflash
|
||||
self.read_pmt = read_pmt
|
||||
|
||||
def get_gpt(self, gpt_num_part_entries, gpt_part_entry_size, gpt_part_entry_start_lba, parttype="user"):
|
||||
def get_gpt(self, gpt_settings, parttype="user"):
|
||||
data = self.readflash(addr=0, length=2 * self.config.pagesize, filename="", parttype=parttype, display=False)
|
||||
if data[:9] == b"EMMC_BOOT" and self.read_pmt is not None:
|
||||
partdata, partentries = self.read_pmt()
|
||||
|
@ -31,9 +31,9 @@ class Partition(metaclass=LogBase):
|
|||
if data == b"":
|
||||
return None, None
|
||||
guid_gpt = gpt(
|
||||
num_part_entries=gpt_num_part_entries,
|
||||
part_entry_size=gpt_part_entry_size,
|
||||
part_entry_start_lba=gpt_part_entry_start_lba,
|
||||
num_part_entries=gpt_settings.gpt_num_part_entries,
|
||||
part_entry_size=gpt_settings.gpt_part_entry_size,
|
||||
part_entry_start_lba=gpt_settings.gpt_part_entry_start_lba,
|
||||
)
|
||||
header = guid_gpt.parseheader(data, self.config.pagesize)
|
||||
sectors = header.first_usable_lba
|
||||
|
|
|
@ -384,7 +384,7 @@ class xflashext(metaclass=LogBase):
|
|||
return False
|
||||
hwc = self.cryptosetup()
|
||||
sc_org = seccfg(hwc)
|
||||
data, guid_gpt = self.xflash.partition.get_gpt(0, 0, 0, "user")
|
||||
data, guid_gpt = self.xflash.partition.get_gpt(self.mtk.config.gpt_settings, "user")
|
||||
seccfg_data = None
|
||||
partition = None
|
||||
for rpartition in guid_gpt.partentries:
|
||||
|
|
|
@ -2,7 +2,6 @@ import os
|
|||
import logging
|
||||
from mtkclient.Library.utils import LogBase
|
||||
|
||||
|
||||
class damodes:
|
||||
DEFAULT = 0
|
||||
XFLASH = 1
|
||||
|
@ -1468,6 +1467,7 @@ class Mtk_Config(metaclass=LogBase):
|
|||
self.meid = None
|
||||
self.target_config = None
|
||||
self.chipconfig = chipconfig()
|
||||
self.gpt_settings = None
|
||||
if loglevel == logging.DEBUG:
|
||||
logfilename = os.path.join("logs", "log.txt")
|
||||
fh = logging.FileHandler(logfilename)
|
||||
|
|
Loading…
Reference in a new issue