Add support for reading flash of IoT devices (mt6261/mt2301)

This commit is contained in:
Bjoern Kerler 2023-04-21 18:52:25 +02:00
parent a3466d3bf3
commit 2bb83de4c1
No known key found for this signature in database
GPG key ID: 52E823BB96A55380
8 changed files with 500 additions and 93 deletions

View file

@ -265,6 +265,12 @@ Read full flash to filename flash.bin (use --preloader for brom)
python mtk rf flash.bin
```
Read full flash to filename flash.bin (use --preloader for brom) for IoT devices (MT6261/MT2301):
```
python mtk rf flash.bin --iot
```
Read flash offset 0x128000 with length 0x200000 to filename flash.bin (use --preloader for brom)
```

1
mtk
View file

@ -298,6 +298,7 @@ if __name__ == '__main__':
parser_rf.add_argument('--filename', help='Optional filename')
parser_rf.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
parser_rf.add_argument('--socid', help='Read Soc ID')
parser_rf.add_argument('--iot', help='Use special mode for iot MT6261/2301', action="store_true", default=False)
parser_rs.add_argument('startsector', help='Sector to start reading (int or hex)')
parser_rs.add_argument('sectors', help='Sector count')

View file

@ -116,6 +116,7 @@ class DAconfig(metaclass=LogBase):
self.mtk = mtk
self.pathconfig = pathconfig()
self.config = self.mtk.config
self.iot = False
self.usbwrite = self.mtk.port.usbwrite
self.usbread = self.mtk.port.usbread
self.flashsize = 0
@ -235,8 +236,7 @@ class DAconfig(metaclass=LogBase):
if self.da_loader is None:
self.da_loader = loader
self.loader = loader.loader
if self.da_loader is None:
if self.da_loader is None and dacode != 0x6261:
self.error("No da_loader config set up")
return self.da_loader

View file

@ -96,7 +96,7 @@ class DA_handler(metaclass=LogBase):
self.info("Device is unprotected.")
# if not mtk.config.is_brom:
# self.mtk.preloader.reset_to_brom()
if mtk.config.is_brom:
if mtk.config.is_brom and not mtk.config.iot:
self.info("Device is in BROM-Mode. Bypassing security.")
mtk = mtk.bypass_security() # Needed for dumping preloader
if mtk is not None:
@ -107,8 +107,10 @@ class DA_handler(metaclass=LogBase):
preloader = self.dump_preloader_ram()
if preloader is None:
self.error("Failed to dump preloader from ram.")
else:
elif not mtk.config.is_brom:
self.info("Device is in Preloader-Mode :(")
else:
self.info("Device is in BROM-Mode. Iot Mode :)")
if preloader is not None and mtk.config.preloader is None:
@ -253,6 +255,7 @@ class DA_handler(metaclass=LogBase):
else:
length = self.mtk.daloader.daconfig.flashsize
print(f"Dumping sector 0 with flash size {hex(length)} as {filename}.")
sys.stdout.flush()
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:

View file

@ -3,6 +3,7 @@
# (c) B.Kerler 2018-2021 GPLv3 License
import logging
import os
import sys
import time
from struct import pack, unpack
from binascii import hexlify
@ -64,6 +65,52 @@ class norinfo:
res += f"m_sdmmc_cid = {hexlify(val).decode('utf-8')}\n"
return res
class norinfo_iot:
m_nor_ret = None
m_nor_chip_select = None
m_nor_flash_id = None
m_nor_flash_size = None
m_nor_flash_dev_code = None
m_nor_flash_otp_status = None
m_nor_flash_otp_size = None
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
self.m_nor_ret = sh.dword(True)
self.m_nor_chip_select = sh.bytes(2)
self.m_nor_flash_id = sh.short(True)
self.m_nor_flash_size = sh.dword(True)
self.m_nor_flash_size_die1 = sh.dword(True)
self.m_nor_flash_dev_code = sh.shorts(4, True)
self.m_nor_flash_otp_status = sh.dword(True)
self.m_nor_flash_otp_size = sh.dword(True)
self.m_nor_flash_id_die2 = sh.short(True)
self.m_nor_flash_size_die2 = sh.dword(True)
self.m_nor_flash_dev_code_die2 = sh.shorts(4, True)
self.m_nor_flash_otp_status_die2 = sh.dword(True)
self.m_nor_flash_otp_size_die2 = sh.dword(True)
def __repr__(self):
res = f"m_nor_ret = {hex(self.m_nor_ret)}\n"
res += f"m_nor_chip_select = {hexlify(self.m_nor_chip_select).decode('utf-8')}\n"
res += f"m_nor_flash_id = {hex(self.m_nor_flash_id)}\n"
res += f"m_nor_flash_size = {hex(self.m_nor_flash_size)}\n"
val = pack("<HHHH", self.m_nor_flash_dev_code[0], self.m_nor_flash_dev_code[1], self.m_nor_flash_dev_code[2],
self.m_nor_flash_dev_code[3])
res += f"m_nor_flash_dev_code = {hexlify(val).decode('utf-8')}\n"
res += f"m_nor_flash_otp_status = {hex(self.m_nor_flash_otp_status)}\n"
res += f"m_nor_flash_otp_size = {hex(self.m_nor_flash_otp_size)}\n"
res += f"m_nor_flash_id_die2 = {hex(self.m_nor_flash_id)}\n"
res += f"m_nor_flash_size_die2 = {hex(self.m_nor_flash_size)}\n"
val = pack("<HHHH", self.m_nor_flash_dev_code[0], self.m_nor_flash_dev_code[1], self.m_nor_flash_dev_code[2],
self.m_nor_flash_dev_code[3])
res += f"m_nor_flash_dev_code_die2 = {hexlify(val).decode('utf-8')}\n"
res += f"m_nor_flash_otp_status_die2 = {hex(self.m_nor_flash_otp_status)}\n"
res += f"m_nor_flash_otp_size_die2 = {hex(self.m_nor_flash_otp_size)}\n"
return res
class nandinfo32:
m_nand_info = None
@ -93,6 +140,49 @@ class nandinfo32:
return res
class nandinfo_iot:
m_nand_info = None
m_nand_chip_select = None
m_nand_flash_id = None
m_nand_flash_size = None
m_nand_flash_id_count = None
info2 = None
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
self.m_nand_info = sh.dword(True)
self.m_nand_chip_select = sh.bytes()
self.m_nand_flash_id = sh.short(True)
self.m_nand_flash_size = sh.dword(True)
self.m_nand_flash_dev_code = sh.shorts(4, True)
self.m_nand_flash_dev_code_part2 = sh.shorts(4, True)
self.m_nand_pagesize = sh.short()
self.m_nand_sparesize = sh.short()
self.m_nand_pages_per_block = sh.short()
self.m_nand_io_interface = sh.bytes()
self.m_nand_addr_cycle = sh.bytes()
self.info2 = None
def __repr__(self):
res = f"m_nand_info = {hex(self.m_nand_info)}\n"
res += f"m_nand_chip_select = {hex(self.m_nand_chip_select)}\n"
res += f"m_nand_flash_id = {hex(self.m_nand_flash_id)}\n"
res += f"m_nand_flash_size = {hex(self.m_nand_flash_size)}\n"
val = pack("<HHHH", self.m_nand_flash_dev_code[0], self.m_nand_flash_dev_code[1], self.m_nand_flash_dev_code[2],
self.m_nand_flash_dev_code[3])
res += f"m_nand_flash_dev_code = {hexlify(val).decode('utf-8')}\n"
val = pack("<HHHH", self.m_nand_flash_dev_code_part2[0], self.m_nand_flash_dev_code_part2[1], self.m_nand_flash_dev_code_part2[2],
self.m_nand_flash_dev_code_part2[3])
res += f"m_nand_flash_dev_code_part2 = {hexlify(val).decode('utf-8')}\n"
res += f"m_nand_pagesize = {hex(self.m_nand_pagesize)}\n"
res += f"m_nand_sparesize = {hex(self.m_nand_sparesize)}\n"
res += f"m_nand_pages_per_block = {hex(self.m_nand_pages_per_block)}\n"
res += f"m_nand_io_interface = {hex(self.m_nand_io_interface)}\n"
res += f"m_nand_addr_cycle = {hex(self.m_nand_addr_cycle)}\n"
return res
class nandinfo64:
m_nand_info = None
m_nand_chip_select = None
@ -194,6 +284,46 @@ class emmcinfo:
return res
class emmcinfo_iot:
m_emmc_ret = None
m_emmc_boot1_size = None
m_emmc_boot2_size = None
m_emmc_rpmb_size = None
m_emmc_gp_size = None
m_emmc_ua_size = None
m_emmc_cid = None
m_emmc_fwver = None
def __init__(self, config: Mtk_Config, data=None):
if data is None:
return
sh = structhelper(data)
self.config = config
self.m_emmc_ret = sh.dword(True)
self.m_emmc_manufacturer_id = sh.bytes()
self.m_emmc_product_name = sh.bytes(6)
self.m_emmc_partitioned = sh.bytes()
self.m_emmc_boot1_size = sh.dword(True)
self.m_emmc_boot2_size = sh.dword(True)
self.m_emmc_rpmb_size = sh.dword(True)
self.m_emmc_gp_size = sh.dwords(4, True)
self.m_emmc_ua_size = sh.dword(True)
def __repr__(self):
res = f"m_emmc_ret = {hex(self.m_emmc_ret)}\n"
res += f"m_emmc_manufacturer_id = {hex(self.m_emmc_manufacturer_id)}\n"
res += f"m_emmc_product_name = {self.m_emmc_product_name.hex()}\n"
res += f"m_emmc_partitioned = {hex(self.m_emmc_partitioned)}\n"
res += f"m_emmc_boot1_size = {hex(self.m_emmc_boot1_size)}\n"
res += f"m_emmc_boot2_size = {hex(self.m_emmc_boot2_size)}\n"
res += f"m_emmc_rpmb_size = {hex(self.m_emmc_rpmb_size)}\n"
res += f"m_emmc_gp_size[0] = {hex(self.m_emmc_gp_size[0])}\n"
res += f"m_emmc_gp_size[1] = {hex(self.m_emmc_gp_size[1])}\n"
res += f"m_emmc_gp_size[2] = {hex(self.m_emmc_gp_size[2])}\n"
res += f"m_emmc_gp_size[3] = {hex(self.m_emmc_gp_size[3])}\n"
res += f"m_emmc_ua_size = {hex(self.m_emmc_ua_size)}\n"
return res
class sdcinfo:
m_sdmmc_info = None
m_sdmmc_ua_size = None
@ -247,6 +377,34 @@ class configinfo:
res += "randomid = 0x%X%X\n" % (self.randomid[0], self.randomid[1])
return res
class configinfo_iot:
m_int_sram_ret = None
m_int_sram_size = None
m_ext_ram_ret = None
m_ext_ram_type = None
m_ext_ram_chip_select = None
m_ext_ram_size = None
def __init__(self, data):
sh = structhelper(data)
self.m_int_sram_ret = sh.dword(True)
self.m_int_sram_size = sh.dword(True)
self.m_ext_ram_ret = sh.dword(True)
self.m_ext_ram_type = sh.bytes()
self.m_ext_ram_chip_select = sh.bytes()
self.m_ext_ram_size = sh.dword(True)
self.sf_candidate = sh.bytes(12)
def __repr__(self):
res = "m_int_sram_ret = 0x%X\n" % self.m_int_sram_ret
res += "m_int_sram_size = 0x%X\n" % self.m_int_sram_size
res += "m_ext_ram_ret = 0x%X\n" % self.m_ext_ram_ret
res += "m_ext_ram_type = 0x%X\n" % self.m_ext_ram_type
res += "m_ext_ram_chip_select = 0x%X\n" % self.m_ext_ram_chip_select
res += "m_int_sram_ret = 0x%X\n" % self.m_int_sram_ret
res += f"m_ext_ram_size = {hex(self.m_ext_ram_size)}\n"
res += f"sf_candidate = {self.sf_candidate.hex()}\n"
return res
class passinfo:
ack = None
@ -990,6 +1148,38 @@ class DALegacy(metaclass=LogBase):
return False
return True
def read_flash_info_iot(self):
self.nor = norinfo_iot(self.usbread(0x36))
self.nand = nandinfo_iot(self.usbread(0x23))
self.emmc = emmcinfo_iot(self.config,self.usbread(0x2C))
self.flashconfig = configinfo_iot(self.usbread(0x1E))
ack=self.usbread(1)
ack=self.usbread(1)
m_download_status=int.from_bytes(self.usbread(4),'big')
m_boot_style = int.from_bytes(self.usbread(4), 'big')
soc_ok=self.usbread(1)
if soc_ok==b"\xC1":
# Security pre-process
self.usbwrite(b"\x59")
ack2=self.usbread(1)
if ack2==b"\xA5":
# Get Fat Info:
self.usbwrite(b"\xF0")
status=self.usbread(4)
nor_addr=int.from_bytes(self.usbread(4),'big')
nor_len = int.from_bytes(self.usbread(4), 'big')
nand_addr = int.from_bytes(self.usbread(4), 'big')
nand_len = int.from_bytes(self.usbread(4), 'big')
emmc_addr = int.from_bytes(self.usbread(4), 'big')
emmc_len = int.from_bytes(self.usbread(4), 'big')
print(f"Nor addr/len: {hex(nor_addr)}/{hex(nor_len)}")
print(f"Nand addr/len: {hex(nand_addr)}/{hex(nand_len)}")
print(f"EMMC addr/len: {hex(emmc_addr)}/{hex(emmc_len)}")
sys.stdout.flush()
return True
return False
def read_flash_info(self):
self.nor = norinfo(self.usbread(0x1C))
data = self.usbread(0x11)
@ -1016,53 +1206,53 @@ class DALegacy(metaclass=LogBase):
return False
def upload(self):
if self.daconfig.da_loader is None:
self.error("No valid da loader found... aborting.")
return False
loader = self.daconfig.loader
self.info(f"Uploading legacy stage 1 from {os.path.basename(loader)}")
with open(loader, 'rb') as bootldr:
# stage 1
da1offset = self.daconfig.da_loader.region[1].m_buf
da1size = self.daconfig.da_loader.region[1].m_len
da1address = self.daconfig.da_loader.region[1].m_start_addr
da2address = self.daconfig.da_loader.region[1].m_start_addr
da1sig_len = self.daconfig.da_loader.region[1].m_sig_len
bootldr.seek(da1offset)
da1 = bootldr.read(da1size)
# ------------------------------------------------
da2offset = self.daconfig.da_loader.region[2].m_buf
da2sig_len = self.daconfig.da_loader.region[2].m_sig_len
bootldr.seek(da2offset)
da2 = bootldr.read(self.daconfig.da_loader.region[2].m_len)
if self.mtk.config.is_brom or not self.mtk.config.target_config["sbc"]:
hashaddr, hashmode, hashlen = self.mtk.daloader.compute_hash_pos(da1, da2, da2sig_len)
if hashaddr is not None:
da2patched = self.lft.patch_da2(da2)
if da2patched != da2:
da1 = self.mtk.daloader.fix_hash(da1, da2patched, hashaddr, hashmode, hashlen)
self.patch = True
self.daconfig.da2 = da2patched[:hashlen]+da2[hashlen:hashlen+da2sig_len]
if not self.config.iot:
if self.daconfig.da_loader is None:
self.error("No valid da loader found... aborting.")
return False
loader = self.daconfig.loader
self.info(f"Uploading legacy stage 1 from {os.path.basename(loader)}")
with open(loader, 'rb') as bootldr:
# stage 1
da1offset = self.daconfig.da_loader.region[1].m_buf
da1size = self.daconfig.da_loader.region[1].m_len
da1address = self.daconfig.da_loader.region[1].m_start_addr
da2address = self.daconfig.da_loader.region[1].m_start_addr
da1sig_len = self.daconfig.da_loader.region[1].m_sig_len
bootldr.seek(da1offset)
da1 = bootldr.read(da1size)
# ------------------------------------------------
da2offset = self.daconfig.da_loader.region[2].m_buf
da2sig_len = self.daconfig.da_loader.region[2].m_sig_len
bootldr.seek(da2offset)
da2 = bootldr.read(self.daconfig.da_loader.region[2].m_len)
if self.mtk.config.is_brom or not self.mtk.config.target_config["sbc"]:
hashaddr, hashmode, hashlen = self.mtk.daloader.compute_hash_pos(da1, da2, da2sig_len)
if hashaddr is not None:
da2patched = self.lft.patch_da2(da2)
if da2patched != da2:
da1 = self.mtk.daloader.fix_hash(da1, da2patched, hashaddr, hashmode, hashlen)
self.patch = True
self.daconfig.da2 = da2patched[:hashlen]+da2[hashlen:hashlen+da2sig_len]
else:
self.daconfig.da2 = da2[:hashlen]+da2[hashlen:hashlen+da2sig_len]
else:
self.daconfig.da2 = da2[:hashlen]+da2[hashlen:hashlen+da2sig_len]
self.daconfig.da2 = da2[:-da2sig_len]
else:
self.daconfig.da2 = da2[:-da2sig_len]
else:
self.daconfig.da2 = da2[:-da2sig_len]
if self.mtk.preloader.send_da(da1address, da1size, da1sig_len, da1):
if self.mtk.preloader.jump_da(da1address):
sync = self.usbread(1)
if sync != b"\xC0":
self.error("Error on DA sync")
return False
if self.mtk.preloader.send_da(da1address, da1size, da1sig_len, da1):
if self.mtk.preloader.jump_da(da1address):
sync = self.usbread(1)
if sync != b"\xC0":
self.error("Error on DA sync")
return False
else:
self.info("Got loader sync !")
else:
self.info("Got loader sync !")
return False
else:
return False
else:
return False
self.info("Reading nand info")
nandinfo = unpack(">I", self.usbread(4))[0]
self.debug("NAND_INFO: " + hex(nandinfo))
@ -1122,7 +1312,119 @@ class DALegacy(metaclass=LogBase):
else:
return False
return True
return False
return False
else: # MT6261
with open(os.path.join("mtkclient","Loader","mt6261_da1.bin"), 'rb') as bootldr:
da1 = bootldr.read()
da1size = len(da1)
da1address = 0x70007000
da1sig_len = 0x100
with open(os.path.join("mtkclient","Loader","mt6261_da2.bin"), 'rb') as bootldr:
da2 = bootldr.read()
da2size = len(da2)
da2address = 0x10020000
da2sig_len = 0x100
if self.mtk.preloader.send_da(da1address, da1size, da1sig_len, da1):
if self.mtk.preloader.send_da(da2address, da2size, da2sig_len, da2):
if self.mtk.preloader.jump_da(da1address):
sync = self.usbread(1)
if sync != b"\xC0":
self.error("Error on DA sync")
return False
else:
self.info("Got loader sync !")
else:
return False
else:
return False
else:
return False
da_maj = self.usbread(1)
da_min = self.usbread(1)
baseband_chip = self.usbread(1)
#Disable Download Without Battery
self.usbwrite(b"\xA5")
# Brom Version
self.usbwrite(b"\x05")
# BLOADER Version
self.usbwrite(b"\xFE")
# NOR_CFG: m_nor_chip_select
self.usbwrite(b"\x00\x08")
# m_nand_chip_select
self.usbwrite(b"\x00")
# m_nand_acccon
self.usbwrite(b"\x70\x07\xFF\xFF")
# ext_clock(0x02)="EXT_26M"
self.usbwrite(b"\x02")
self.usbwrite(b"\x00\x00\x01\x03")
ack=self.usbread(1)
if ack!=b"Z":
return False
self.usbwrite(bytes.fromhex("D2 00 00 00 DC 17 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 01 00 00 00 00 00 68 17 04 10 00 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D3 00 00 00 1C 18 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 02 00 00 00 00 00 68 17 04 10 00 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D4 00 00 00 5C 18 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 03 00 00 00 00 00 68 17 04 10 00 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D5 00 00 00 9C 17 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 28 00 00 00 00 00 68 17 04 10 00 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D6 00 00 00 DC 17 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 21 00 00 00 00 00 68 17 04 10 00 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D7 00 00 00 1C 18 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 22 00 00 00 00 00 68 17 04 1000 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D8 00 00 00 5C 18 04 10 64 01 04 10 00 00 00 00 01 00 BF 00 26 00 23 00 00 00 00 00 68 17 04 1000 00 00 00"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("D9 00 00 00 D4 1F 04 10 64 01 04 10 4C 19 04 10 01 00 C2 00 25 00 34 00 00 00 00 00 CC 18 04 10 34 19 04 10"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("10 01 00 00 D4 1F 04 10 64 01 04 10 4C 19 04 10 01 00 C2 00 20 00 14 00 00 00 00 00 CC 18 04 10 34 19 04 10"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("DA 00 00 00 14 20 04 10 64 01 04 10 4C 19 04 10 01 00 C2 00 25 00 35 00 00 00 00 00 CC 18 04 10 34 19 04 10"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("DB 00 00 00 54 20 04 10 64 01 04 10 4C 19 04 10 01 00 C2 00 25 00 36 00 00 00 00 00 CC 18 04 10 34 19 04 10"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("DC 00 00 00 94 20 04 10 64 01 04 10 4C 19 04 10 01 00 C2 00 25 00 37 00 00 00 00 00 CC 18 04 10 34 19 04 10"))
if self.usbread(1)!=b"i":
return False
self.usbwrite(bytes.fromhex("EF 00 00 00 D4 20 04 10 64 01 04 10 4C 19 04 10 01 00 C2 00 25 00 38 00 00 00 00 00 CC 18 04 10 34 19 04 10"))
v1=self.usbread(1)
if v1 == b"Z":
v1 = self.usbread(1)
self.usbwrite(b"\x00\x00\x00\x00")
info=int.from_bytes(self.usbread(4),'little')
if self.read_flash_info_iot():
if self.nand.m_nand_flash_size != 0:
self.daconfig.flashtype = "nand"
elif self.emmc.m_emmc_ua_size != 0:
self.daconfig.flashtype = "emmc"
else:
self.daconfig.flashtype = "nor"
if self.daconfig.flashtype == "nand":
self.daconfig.flashsize = self.nand.m_nand_flash_size
elif self.daconfig.flashtype == "emmc" or self.emmc.m_emmc_ua_size != 0:
self.daconfig.flashsize = self.emmc.m_emmc_ua_size
self.daconfig.flashtype = "emmc"
if self.daconfig.flashsize == 0:
self.daconfig.flashsize = self.sdc.m_sdmmc_ua_size
elif self.daconfig.flashtype == "nor":
self.daconfig.flashsize = self.nor.m_nor_flash_size
return True
return False
def upload_da(self):
self.info("Uploading legacy da...")
@ -1333,11 +1635,11 @@ class DALegacy(metaclass=LogBase):
while progress != 100:
ack = self.usbread(1)[0]
if ack is not self.Rsp.ACK[0]:
self.error(f"Error on sending emmc read command, response: {hex(ack)}")
self.error(f"Error on sending emmc format command, response: {hex(ack)}")
exit(1)
ack = self.usbread(1)[0]
if ack is not self.Rsp.ACK[0]:
self.error(f"Error on sending emmc read command, response: {hex(ack)}")
self.error(f"Error on sending emmc format command, response: {hex(ack)}")
exit(1)
data = self.usbread(4)[0] # PROGRESS_INIT
progress = self.usbread(1)[0]
@ -1345,46 +1647,57 @@ class DALegacy(metaclass=LogBase):
if progress == 0x64:
ack = self.usbread(1)[0]
if ack is not self.Rsp.ACK[0]:
self.error(f"Error on sending emmc read command, response: {hex(ack)}")
self.error(f"Error on sending emmc format command, response: {hex(ack)}")
exit(1)
ack = self.usbread(1)[0]
if ack is not self.Rsp.ACK[0]:
self.error(f"Error on sending emmc read command, response: {hex(ack)}")
self.error(f"Error on sending emmc format command, response: {hex(ack)}")
exit(1)
return True
return False
def get_parttype(self, length, parttype):
if parttype is None or parttype == "user" or parttype == "":
length = min(length, self.emmc.m_emmc_ua_size)
if self.daconfig.flashtype=="emmc":
if parttype is None or parttype == "user" or parttype == "":
length = min(length, self.emmc.m_emmc_ua_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
elif parttype == "boot1":
length = min(length, self.emmc.m_emmc_boot1_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT1
elif parttype == "boot2":
length = min(length, self.emmc.m_emmc_boot2_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT2
elif parttype == "gp1":
length = min(length, self.emmc.m_emmc_gp_size[0])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP1
elif parttype == "gp2":
length = min(length, self.emmc.m_emmc_gp_size[1])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP2
elif parttype == "gp3":
length = min(length, self.emmc.m_emmc_gp_size[2])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP3
elif parttype == "gp4":
length = min(length, self.emmc.m_emmc_gp_size[3])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP4
elif parttype == "rpmb":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_RPMB
elif self.daconfig.flashtype == "nand":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
elif parttype == "boot1":
length = min(length, self.emmc.m_emmc_boot1_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT1
elif parttype == "boot2":
length = min(length, self.emmc.m_emmc_boot2_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT2
elif parttype == "gp1":
length = min(length, self.emmc.m_emmc_gp_size[0])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP1
elif parttype == "gp2":
length = min(length, self.emmc.m_emmc_gp_size[1])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP2
elif parttype == "gp3":
length = min(length, self.emmc.m_emmc_gp_size[2])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP3
elif parttype == "gp4":
length = min(length, self.emmc.m_emmc_gp_size[3])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP4
elif parttype == "rpmb":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_RPMB
length = min(length,self.nand.m_nand_flash_size)
elif self.daconfig.flashtype == "nor":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.nor.m_nor_flash_size)
else:
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.sdc.m_sdmmc_ua_size)
return length, parttype
def readflash(self, addr, length, filename, parttype=None, display=True):
global rq
self.mtk.daloader.progress.clear()
length, parttype = self.get_parttype(length, parttype)
self.check_usb_cmd()
if not self.config.iot:
self.check_usb_cmd()
packetsize = 0x0
if self.daconfig.flashtype == "emmc":
self.sdmmc_switch_part(parttype)
@ -1422,6 +1735,27 @@ class DALegacy(metaclass=LogBase):
self.usbread(4)
self.daconfig.readsize = self.daconfig.flashsize // self.daconfig.pagesize * (
self.daconfig.pagesize + self.daconfig.sparesize)
elif self.daconfig.flashtype == "nor":
packetsize = 0x400
self.usbwrite(self.Cmd.READ_CMD) # D6
if not self.config.iot:
self.usbwrite(b"\x0C") # Host:Linux, 0x0B=Windows
self.usbwrite(b"\x00") # Storage-Type: EMMC
if self.config.iot:
self.usbwrite(pack(">I", addr))
self.usbwrite(pack(">I", length))
self.usbwrite(pack(">I", packetsize))
else:
self.usbwrite(pack(">Q", addr))
self.usbwrite(pack(">Q", length))
self.usbwrite(pack(">I", packetsize))
ack = self.usbread(1)[0]
if ack is not self.Rsp.ACK[0]:
self.usbwrite(b"\xA5")
res = unpack("<I", self.usbread(4))[0]
self.error(f"Error on sending emmc read command, response: {hex(ack)}, status: {hex(res)}")
exit(1)
self.daconfig.readsize = self.daconfig.flashsize
if display:
self.mtk.daloader.progress.show_progress("Read", 0, length, display)
if filename != "":

View file

@ -56,8 +56,9 @@ class DAloader(metaclass=LogBase):
config["m_emmc_boot2_size"] = self.da.emmc.m_emmc_boot2_size
config["m_emmc_gp_size"] = self.da.emmc.m_emmc_gp_size
config["m_nand_flash_size"] = self.da.nand.m_nand_flash_size
config["m_sdmmc_ua_size"] = self.da.sdc.m_sdmmc_ua_size
config["m_nor_flash_size"] = self.da.nor.m_nor_flash_size
if not self.mtk.config.iot:
config["m_sdmmc_ua_size"] = self.da.sdc.m_sdmmc_ua_size
open(".state", "w").write(json.dumps(config))

View file

@ -333,6 +333,11 @@ class Main(metaclass=LogBase):
serialport = self.args.serialport
except:
pass
try:
iot = self.args.iot
config.iot = iot
except:
pass
mtk = Mtk(config=config, loglevel=loglevel, serialportname=serialport)
config.set_peek(mtk.daloader.peek)
if mtk.config.debugmode:

View file

@ -160,16 +160,23 @@ class Preloader(metaclass=LogBase):
if tries == 10:
return False
if not self.echo(self.Cmd.GET_HW_CODE.value): # 0xFD
if not self.echo(self.Cmd.GET_HW_CODE.value):
self.error("Sync error. Please power off the device and retry.")
self.config.set_gui_status(self.config.tr("Sync error. Please power off the device and retry."))
return False
if self.config.iot:
self.config.hwver = self.read_a2(0x80000000)
self.config.hwcode = self.read_a2(0x80000008)
self.config.hw_sub_code = self.read_a2(0x8000000C)
self.config.swver = (self.read32(0xA01C0108)&0xFFFF0000)>>16
else:
val = self.rdword()
self.config.hwcode = (val >> 16) & 0xFFFF
self.config.hwver = val & 0xFFFF
self.config.init_hwcode(self.config.hwcode)
if not self.echo(self.Cmd.GET_HW_CODE.value): # 0xFD
if not self.echo(self.Cmd.GET_HW_CODE.value):
self.error("Sync error. Please power off the device and retry.")
self.config.set_gui_status(self.config.tr("Sync error. Please power off the device and retry."))
return False
else:
val = self.rdword()
self.config.hwcode = (val >> 16) & 0xFFFF
self.config.hwver = val & 0xFFFF
self.config.init_hwcode(self.config.hwcode)
self.config.init_hwcode(self.config.hwcode)
cpu = self.config.chipconfig.name
if self.display:
@ -194,16 +201,17 @@ class Preloader(metaclass=LogBase):
self.info("Get Target info")
self.get_blver()
self.get_bromver()
res = self.get_hw_sw_ver()
self.config.hwsubcode = 0
self.config.hwver = 0
self.config.swver = 0
if res != -1:
self.config.hwsubcode = res[0]
self.config.hwver = res[1]
self.config.swver = res[2]
if not self.config.iot:
res = self.get_hw_sw_ver()
self.config.hw_sub_code = 0
self.config.hwver = 0
self.config.swver = 0
if res != -1:
self.config.hw_sub_code = res[0]
self.config.hwver = res[1]
self.config.swver = res[2]
if self.display:
self.info("\tHW subcode:\t\t" + hex(self.config.hwsubcode))
self.info("\tHW subcode:\t\t" + hex(self.config.hw_sub_code))
self.info("\tHW Ver:\t\t\t" + hex(self.config.hwver))
self.info("\tSW Ver:\t\t\t" + hex(self.config.swver))
meid = self.get_meid()
@ -220,6 +228,14 @@ class Preloader(metaclass=LogBase):
self.info("SOC_ID:\t\t\t" + hexlify(socid).decode('utf-8').upper())
return True
def read_a2(self, addr, dwords=1) -> list:
cmd = self.Cmd.CMD_READ16_A2
if self.echo(cmd.value):
if self.echo(pack(">I", addr)):
ack = self.echo(pack(">I", dwords))
return unpack(">H", self.usbread(2))[0]
return None
def read(self, addr, dwords=1, length=32) -> list:
result = []
cmd = self.Cmd.READ16 if length == 16 else self.Cmd.READ32
@ -367,7 +383,48 @@ class Preloader(metaclass=LogBase):
"""
addr, value = self.config.get_watchdog_addr()
if hwcode in [0x6575, 0x6577]:
if hwcode == 0x6261:
#SetLongPressPWKEY
self.read32(0xA01C0108)
self.write16(0xA0700F00,0x41)
self.write16(0xA0700F00, 0x51)
self.write16(0xA0700F00, 0x41)
#SetReg_DisableChargeControl()
self.write16(0xA0700A28,self.read16(0xA0700A28)|0x4000)
self.write16(0xA0700A00,self.read16(0xA0700A00,1)|0x10)
self.write16(0xA0030000, 0x2200)
#SetReg_LockPowerKey
self.read16(0xA0710000,1)
#PowerKeysMatched
self.read16(0xA0710050, 1)
self.read16(0xA0710054, 1)
self.write16(0xA0710010, 0)
self.write16(0xA0710008, 0)
self.write16(0xA071000C, 0)
#Unlock
self.write16(0xA0710074, 1)
val2=self.read16(0xA0710000, 1)
self.write16(0xA0710050, 0xA357)
self.write16(0xA0710054, 0x67D2)
self.read16(0xA0710074, 1)
val2 = self.read16(0xA0710000, 1)
self.write16(0xA0710068, 0x586A)
self.write16(0xA0710074, 1)
self.read16(0xA0710000, 1)
self.write16(0xA0710068, 0x9136)
self.write16(0xA0710074, 1)
self.read16(0xA0710000, 1)
self.write16(0xA0710074, 1)
self.read16(0xA0710000, 1)
# Get Target Config : D8
# SetRemap:
self.write32(0xA0510000,self.read32(0xA0510000,1)|2)
self.write32(0xA0510000, self.read32(0xA0510000, 1) | 2)
res = True
elif hwcode in [0x6575, 0x6577]:
"""
SoCs which share the same watchdog IP as mt6577 must use 16-bit I/O.
For example: mt6575, mt8317 and mt8377 (their hwcodes are 0x6575).