Fix reset/shutdown

This commit is contained in:
Bjoern Kerler 2022-07-06 20:23:56 +02:00
parent 537c8c76bc
commit 727ae63298
No known key found for this signature in database
GPG key ID: 52E823BB96A55380
5 changed files with 128 additions and 27 deletions

32
mtk
View file

@ -20,6 +20,7 @@ cmds = {
"wo": "Write flash starting at offset from filename",
"e": "Erase partition",
"es": "Erase partition with sector count",
"ess": "Erase sector with sector count",
"footer": "Read crypto footer from flash",
"reset": "Send mtk reset command",
"dumpbrom": "Try to dump the bootrom",
@ -72,6 +73,7 @@ if __name__ == '__main__':
parser_wo = subparsers.add_parser("wo", help="Write flash starting at offset from filename")
parser_e = subparsers.add_parser("e", help="Erase partition")
parser_es = subparsers.add_parser("es", help="Erase partition with sector count")
parser_ess = subparsers.add_parser("ess", help="Erase sector with sector count")
parser_footer = subparsers.add_parser("footer", help="Read crypto footer from flash")
parser_reset = subparsers.add_parser("reset", help="Send mtk reset command")
@ -536,6 +538,36 @@ if __name__ == '__main__':
parser_es.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
parser_es.add_argument('--socid', help='Read Soc ID')
parser_ess.add_argument('startsector', help='Startsector to erase')
parser_ess.add_argument('sectors', help='Sectors to erase')
parser_ess.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
parser_ess.add_argument('--vid', type=str, help='Set usb vendor id used for MTK Preloader')
parser_ess.add_argument('--pid', type=str, help='Set usb product id used for MTK Preloader')
parser_ess.add_argument('--sectorsize', default='0x200', help='Set default sector size')
parser_ess.add_argument('--debugmode', action='store_true', default=False, help='Enable verbose mode')
parser_ess.add_argument('--gpt-num-part-entries', default='0', help='Set GPT entry count')
parser_ess.add_argument('--gpt-part-entry-size', default='0', help='Set GPT entry size')
parser_ess.add_argument('--gpt-part-entry-start-lba', default='0', help='Set GPT entry start lba sector')
parser_ess.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_ess.add_argument('--skip', help='Skip reading partition with names "partname1,partname2,etc."')
parser_ess.add_argument('--skipwdt', help='Skip wdt init')
parser_ess.add_argument('--wdt', help='Set a specific watchdog addr')
parser_ess.add_argument('--mode', help='Set a crash mode (0=dasend1,1=dasend2,2=daread)')
parser_ess.add_argument('--var1', help='Set kamakiri specific var1 value')
parser_ess.add_argument('--uart_addr', help='Set payload uart_addr value')
parser_ess.add_argument('--da_addr', help='Set a specific da payload addr')
parser_ess.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_ess.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
parser_ess.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_ess.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_ess.add_argument('--parttype', help='Partition type\n' +
'\t\tEMMC: [user, boot1, boot2, gp1, gp2, gp3, gp4, rpmb]' +
'\t\tUFS: [lu0, lu1, lu2, lu0_lu1]')
parser_ess.add_argument('--filename', help='Optional filename')
parser_ess.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
parser_ess.add_argument('--socid', help='Read Soc ID')
parser_footer.add_argument('filename', help='Filename to store footer')
parser_footer.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
parser_footer.add_argument('--vid', type=str, help='Set usb vendor id used for MTK Preloader')

View file

@ -435,6 +435,37 @@ class DA_handler(metaclass=LogBase):
elif countFP != len(partitions) and countFP > 1:
print(f"Failed to format all partitions.")
def da_ess(self, sector: int, sectors: int, parttype: str):
if parttype == "user" or parttype is None:
wipedata = b"\x00" * 0x200000
error = False
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="user"):
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(sector)} with sector count {str(sectors)}.")
else:
pos = 0
self.mtk.daloader.formatflash(addr=sector * self.mtk.daloader.daconfig.pagesize,
length=min(sectors*self.mtk.daloader.daconfig.pagesize,0xF000000),
partitionname=None,
parttype=parttype,
display=True)
print(f"Formatted sector {str(pos // 0x200)}")
def da_es(self, partitions: list, parttype: str, sectors: int):
if parttype == "user" or parttype is None:
i = 0
@ -478,7 +509,8 @@ class DA_handler(metaclass=LogBase):
else:
pos = 0
for partitionname in partitions:
self.mtk.daloader.formatflash(addr=pos, length=0xF000000, partitionname=partitionname,
self.mtk.daloader.formatflash(addr=pos, length=min(sectors * self.mtk.daloader.daconfig.pagesize,0xF000000),
partitionname=partitionname,
parttype=parttype,
display=True)
print(f"Formatted sector {str(pos // 0x200)}")
@ -648,11 +680,19 @@ class DA_handler(metaclass=LogBase):
self.close()
partitions = partitionname.split(",")
self.da_es(partitions=partitions, parttype=parttype, sectors=sectors)
elif cmd == "ess":
sector = args.startsector
parttype = args.parttype
sectors = getint(args.sectors)
if args.sectors is None:
self.error("Sector count is missing. Usage: ess [sector] [sector count]")
self.close()
self.da_ess(sector=sector, parttype=parttype, sectors=sectors)
elif cmd == "reset":
if os.path.exists(".state"):
os.remove(".state")
os.remove(os.path.join("logs", "hwparam.json"))
mtk.daloader.close()
mtk.daloader.shutdown(bootmode=0)
print("Reset command was sent. Disconnect usb cable to power off.")
elif cmd == "da":
subcmd = args.subcmd

View file

@ -957,11 +957,11 @@ class DALegacy(metaclass=LogBase):
m_ext_ram_size = unpack(">Q", self.usbread(8))[0] # 0x80000000
self.info(f"M_EXT_RAM_SIZE : {hex(m_ext_ram_size)}")
if self.daconfig.emiver in [0x0D]:
self.usbread(4) # 00000003
Raw_0 = self.usbread(4) # 1C004004
Raw_1 = self.usbread(4) # aa080033
CJ_0 = self.usbread(4) # 00000013
CJ_1 = self.usbread(4) # 00000010
self.usbread(4) # 00000003
Raw_0 = self.usbread(4) # 1C004004
Raw_1 = self.usbread(4) # aa080033
CJ_0 = self.usbread(4) # 00000013
CJ_1 = self.usbread(4) # 00000010
else:
self.error("Preloader needed due to dram config.")
self.mtk.port.close(reset=True)
@ -1112,8 +1112,13 @@ class DALegacy(metaclass=LogBase):
return True
return False
def close(self):
self.finish(0x0) # DISCONNECT_USB_AND_RELEASE_POWERKEY
class ShutDownModes:
NORMAL = 0
HOME_SCREEN = 1
FASTBOOT = 2
def shutdown(self, async_mode: int = 0, dl_bit: int = 0, bootmode: ShutDownModes = ShutDownModes.NORMAL):
self.finish(bootmode) # DISCONNECT_USB_AND_RELEASE_POWERKEY
self.mtk.port.close(reset=True)
def brom_send(self, dasetup, dadata, stage, packetsize=0x1000):

View file

@ -16,6 +16,7 @@ from mtkclient.Library.xflash_ext import xflashext
from mtkclient.Library.legacy_ext import legacyext
from mtkclient.Library.settings import hwparam
class DAloader(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
@ -41,7 +42,7 @@ class DAloader(metaclass=LogBase):
def writestate(self):
config = {}
config["xflash"] = self.mtk.config.chipconfig.damode==damodes.XFLASH
config["xflash"] = self.mtk.config.chipconfig.damode == damodes.XFLASH
config["hwcode"] = self.config.hwcode
if self.config.meid is not None:
config["meid"] = hexlify(self.config.meid).decode('utf-8')
@ -49,7 +50,7 @@ class DAloader(metaclass=LogBase):
config["socid"] = hexlify(self.config.socid).decode('utf-8')
config["flashtype"] = self.daconfig.flashtype
config["flashsize"] = self.daconfig.flashsize
if not self.mtk.config.chipconfig.damode==damodes.XFLASH:
if not self.mtk.config.chipconfig.damode == damodes.XFLASH:
config["m_emmc_ua_size"] = self.da.emmc.m_emmc_ua_size
config["m_emmc_boot1_size"] = self.da.emmc.m_emmc_boot1_size
config["m_emmc_boot2_size"] = self.da.emmc.m_emmc_boot2_size
@ -61,7 +62,7 @@ class DAloader(metaclass=LogBase):
open(".state", "w").write(json.dumps(config))
def compute_hash_pos(self, da1, da2, da2sig_len):
hashlen = len(da2)-da2sig_len
hashlen = len(da2) - da2sig_len
hashmode, idx = self.calc_da_hash(da1, da2[:hashlen])
if idx == -1:
@ -118,7 +119,7 @@ class DAloader(metaclass=LogBase):
self.da.nand = nandinfo64()
self.da.emmc = emmcinfo(self.config)
self.da.sdc = sdcinfo(self.config)
self.lft=legacyext(self.mtk, self.da, self.loglevel)
self.lft = legacyext(self.mtk, self.da, self.loglevel)
self.da.emmc.m_emmc_ua_size = config["m_emmc_ua_size"]
self.da.emmc.m_emmc_boot1_size = config["m_emmc_boot1_size"]
self.da.emmc.m_emmc_boot2_size = config["m_emmc_boot2_size"]
@ -152,7 +153,7 @@ class DAloader(metaclass=LogBase):
self.xflash = True
if self.xflash:
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
if porttype not in ["off","usb","uart"]:
if porttype not in ["off", "usb", "uart"]:
self.error("Only \"off\",\"usb\" or \"uart\" are allowed.")
if self.da.set_meta(porttype):
self.info(f"Successfully set meta mode to {porttype}")
@ -192,8 +193,13 @@ class DAloader(metaclass=LogBase):
def upload(self):
return self.da.upload()
def close(self):
return self.da.close()
class ShutDownModes:
NORMAL = 0
HOME_SCREEN = 1
FASTBOOT = 2
def shutdown(self, bootmode=ShutDownModes.NORMAL):
return self.da.shutdown(async_mode=0, dl_bit=0, bootmode=bootmode)
def upload_da(self, preloader=None):
self.daconfig.setup()
@ -213,12 +219,12 @@ class DAloader(metaclass=LogBase):
def get_packet_length(self):
if self.xflash:
pt=self.da.get_packet_length()
pt = self.da.get_packet_length()
return pt.read_packet_length
else:
return 512
def peek(self, addr: int, length:int):
def peek(self, addr: int, length: int):
if self.xflash:
return self.xft.custom_read(addr=addr, length=length)
else:
@ -261,4 +267,4 @@ class DAloader(metaclass=LogBase):
if self.xflash:
return self.xft.erase_rpmb()
self.error("Device is not in xflash mode, cannot run erase rpmb cmd.")
return False
return False

View file

@ -174,7 +174,7 @@ class DAXFlash(metaclass=LogBase):
except:
return -1
def xsend(self, data, datatype=DataType.DT_PROTOCOL_FLOW, is64bit:bool = False):
def xsend(self, data, datatype=DataType.DT_PROTOCOL_FLOW, is64bit: bool = False):
if isinstance(data, int):
if is64bit:
data = pack("<Q", data)
@ -515,8 +515,9 @@ class DAXFlash(metaclass=LogBase):
chipid = Chipid
data = self.send_devctrl(self.Cmd.GET_CHIP_ID)
chipid.hw_code, chipid.hw_sub_code, chipid.hw_version, chipid.sw_version, chipid.chip_evolution = unpack("<HHHHH",
data[:(5 * 2)])
chipid.hw_code, chipid.hw_sub_code, chipid.hw_version, chipid.sw_version, chipid.chip_evolution = unpack(
"<HHHHH",
data[:(5 * 2)])
status = self.status()
if status == 0:
self.info("HW-CODE : 0x%X", chipid.hw_code)
@ -778,6 +779,7 @@ class DAXFlash(metaclass=LogBase):
if resp != b"":
status = self.status()
if status == 0:
# full-speed, high-speed, hyper-speed
return resp
else:
self.error(f"Error on getting usb speed: {self.eh.status(status)}")
@ -889,15 +891,31 @@ class DAXFlash(metaclass=LogBase):
return buffer
return False
def close(self):
class ShutDownModes:
NORMAL = 0
HOME_SCREEN = 1
FASTBOOT = 2
def shutdown(self, async_mode: int = 0, dl_bit: int = 0, bootmode: ShutDownModes = ShutDownModes.NORMAL):
if self.xsend(self.Cmd.SHUTDOWN):
status = self.status()
if status == 0:
self.mtk.port.close(reset=True)
return True
hasflags = 0
# bootmode 0: shutdown 1: home screen, 2: fastboot
if async_mode or dl_bit or bootmode > 0:
hasflags = 1
enablewdt = 0 # Disable wdt
dont_resetrtc = 0 # Reset RTC
leaveusb = 0 # Disconnect usb
if self.xsend(pack("<IIIIIIII", hasflags, enablewdt, async_mode, bootmode, dl_bit,
dont_resetrtc, leaveusb, 0)):
status = self.status()
if status == 0:
self.mtk.port.close(reset=True)
return True
else:
self.error(f"Error on sending shutdown: {self.eh.status(status)}")
self.mtk.port.close(True)
self.mtk.port.close(reset=True)
return False
def getstorage(self, parttype, length):
@ -1031,7 +1049,7 @@ class DAXFlash(metaclass=LogBase):
hashaddr, hashmode, hashlen = self.mtk.daloader.compute_hash_pos(da1, da2, da2sig_len)
if hashaddr is not None:
#da1 = self.xft.patch_da1(da1)
# da1 = self.xft.patch_da1(da1)
da2 = self.xft.patch_da2(da2)
da1 = self.mtk.daloader.fix_hash(da1, da2, hashaddr, hashmode, hashlen)
self.patch = True