mirror of
https://github.com/bkerler/mtkclient.git
synced 2024-11-14 19:25:05 -05:00
New version. MANY fixes and kewl new stuff. Hopefully more stable now.
This commit is contained in:
parent
81b6622e2f
commit
65db5b344b
818 changed files with 1719 additions and 770 deletions
130
README.md
130
README.md
|
@ -1,6 +1,7 @@
|
|||
# mtkclient
|
||||
Just some mtk tool for exploitation, reading/writing flash and doing crazy stuff. For linux, a patched kernel is only needed for kamakiri (see Setup folder) (except for read/write flash).
|
||||
Just some mtk tool for exploitation, reading/writing flash and doing crazy stuff.
|
||||
For windows, you need to install the stock mtk port and the usbdk driver (see instructions below).
|
||||
For linux, a patched kernel is only needed when using old kamakiri (see Setup folder) (except for read/write flash).
|
||||
|
||||
Once the mtk script is running, boot into brom mode by powering off device, press and hold either
|
||||
vol up + power or vol down + power and connect the phone. Once detected by the tool,
|
||||
|
@ -113,6 +114,80 @@ sudo reboot
|
|||
|
||||
## Usage
|
||||
|
||||
### Root the phone (Tested with android 9 - 12)
|
||||
|
||||
1. Dump boot and vbmeta
|
||||
```
|
||||
python mtk r boot,vbmeta boot.img,vbmeta.img
|
||||
```
|
||||
|
||||
2. Reboot the phone
|
||||
```
|
||||
python mtk reset
|
||||
```
|
||||
|
||||
3. Download patched magisk for mtk:
|
||||
Download [here][https://raw.githubusercontent.com/vvb2060/magisk_files/44ca9ed38c29e22fa276698f6c03bc1168df2c10/app-release.apk]
|
||||
|
||||
4. Install on target phone
|
||||
- you need to enable usb-debugging via Settings/About phone/Version, Tap 7x on build number
|
||||
- Go to Settings/Additional settings/Developer options, enable "OEM unlock" and "USB Debugging"
|
||||
- Install magisk apk
|
||||
```
|
||||
adb install app-release.apk
|
||||
```
|
||||
- accept auth rsa request on mobile screen of course to allow adb connection
|
||||
|
||||
5. Upload boot to /sdcard/Download
|
||||
```
|
||||
adb push boot.img /sdcard/Download
|
||||
```
|
||||
|
||||
6. Start magisk, tap on Install, select boot.img from /sdcard/Download, then:
|
||||
```
|
||||
adb pull /sdcard/Download/[displayed magisk patched boot filename here]
|
||||
mv [displayed magisk patched boot filename here] boot.patched
|
||||
```
|
||||
|
||||
7. Do the steps needed in section "Unlock bootloader below"
|
||||
|
||||
8. Flash magisk-patched boot and empty vbmeta
|
||||
```
|
||||
python mtk w boot,vbmeta boot.patched,vbmeta.img.empty
|
||||
```
|
||||
|
||||
9. Reboot the phone
|
||||
```
|
||||
python mtk reset
|
||||
```
|
||||
|
||||
10. Disconnect usb cable and enjoy your rooted phone :)
|
||||
|
||||
|
||||
### Unlock bootloader
|
||||
|
||||
1. Erase metadata and userdata (and md_udt if existing):
|
||||
```
|
||||
python mtk e metadata, userdata
|
||||
```
|
||||
|
||||
2. Unlock bootloader:
|
||||
```
|
||||
python mtk xflash seccfg unlock
|
||||
```
|
||||
for relocking use:
|
||||
```
|
||||
python mtk xflash seccfg lock
|
||||
```
|
||||
|
||||
3. Reboot the phone:
|
||||
```
|
||||
python mtk reset
|
||||
```
|
||||
|
||||
and disconnect usb cable to let the phone reboot.
|
||||
|
||||
|
||||
### Read flash
|
||||
|
||||
Dump boot partition to filename boot.bin via preloader
|
||||
|
@ -170,16 +245,47 @@ python mtk wl out
|
|||
|
||||
### Erase flash
|
||||
|
||||
Erase boot partition (use --preloader for brom)
|
||||
Erase boot partition
|
||||
```
|
||||
python mtk e boot
|
||||
```
|
||||
|
||||
### Leave flash mode and reboot
|
||||
Erase boot sectors
|
||||
```
|
||||
python mtk reset
|
||||
python mtk es boot [sector count]
|
||||
```
|
||||
|
||||
### XFlash commands (only available via XFlash da, not legacy da for now):
|
||||
|
||||
Peek memory
|
||||
```
|
||||
python mtk xflash peek [addr in hex] [length in hex] [optional: -filename filename.bin for reading to file]
|
||||
```
|
||||
|
||||
Poke memory
|
||||
```
|
||||
python mtk xflash peek [addr in hex] [data as hexstring or -filename for reading from file]
|
||||
```
|
||||
|
||||
Read rpmb
|
||||
```
|
||||
python mtk xflash rpmb r [will read to rpmb.bin]
|
||||
```
|
||||
|
||||
Write rpmb [Dangerous and may not work as it's not tested !]
|
||||
```
|
||||
python mtk xflash rpmb w filename
|
||||
```
|
||||
|
||||
Generate and display rpmb1-3 key
|
||||
```
|
||||
python mtk xflash generatekeys
|
||||
```
|
||||
|
||||
Unlock / Lock bootloader
|
||||
```
|
||||
python mtk xflash seccfg [lock or unlock]
|
||||
```
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -273,8 +379,6 @@ python stage2 preloader
|
|||
### Read memory as hex data in stage2 mode
|
||||
``
|
||||
python stage2 memread [start addr] [length]
|
||||
python stage2 memread 0x140000 0x10
|
||||
python stage2 memread 0x140000 16
|
||||
``
|
||||
|
||||
### Read memory to file in stage2 mode
|
||||
|
@ -282,17 +386,19 @@ python stage2 memread 0x140000 16
|
|||
python stage2 memread [start addr] [length] --filename filename.bin
|
||||
``
|
||||
|
||||
### Write data to memory in stage2 mode
|
||||
### Write hex data to memory in stage2 mode
|
||||
``
|
||||
python stage2 memwrite [start addr] [data as hexstring or hex int or filename]
|
||||
python stage2 memwrite 0x140000 112233445566778899
|
||||
python stage2 memwrite 0x140000 0x12345678
|
||||
python stage2 memwrite 0x140000 data.bin
|
||||
python stage2 memwrite [start addr] --data [data as hexstring]
|
||||
``
|
||||
|
||||
### Write memory from file in stage2 mode
|
||||
``
|
||||
python stage2 memwrite [start addr] --filename filename.bin
|
||||
``
|
||||
|
||||
### Extract keys
|
||||
``
|
||||
python stage2 keys
|
||||
python stage2 keys --mode [sej, dxcc]
|
||||
``
|
||||
For dxcc, you need to use plstage instead of stage
|
||||
|
||||
|
|
213
mtk
213
mtk
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# MTK Flash Client (c) B.Kerler 2018-2021.
|
||||
# Licensed under MIT License
|
||||
import shutil
|
||||
import os
|
||||
import json
|
||||
import sys
|
||||
|
@ -88,6 +89,11 @@ class ArgHandler(metaclass=LogBase):
|
|||
config.preloader = args.preloader
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
if args.generatekeys is not None:
|
||||
config.generatekeys = args.generatekeys
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
if args.ptype is not None:
|
||||
config.ptype = args.ptype
|
||||
|
@ -194,7 +200,7 @@ class Mtk(metaclass=LogBase):
|
|||
def crasher(self, display=True, mode=None):
|
||||
rmtk = self
|
||||
plt = PLTools(self, self.__logger.level)
|
||||
if self.config.enforcecrash or not (self.port.cdc.vid == 0xE8D and self.port.cdc.pid == 0x0003):
|
||||
if self.config.enforcecrash or self.config.meid is None:
|
||||
self.info("We're not in bootrom, trying to crash da...")
|
||||
if mode is None:
|
||||
for crashmode in range(0, 3):
|
||||
|
@ -256,6 +262,7 @@ class Main(metaclass=LogBase):
|
|||
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 mtk.preloader.read32(0x200000 + idx, length + 4 // 4)])
|
||||
preloader = data[:length]
|
||||
idx = data.find(b"MTK_BLOADER_INFO")
|
||||
|
@ -268,7 +275,8 @@ class Main(metaclass=LogBase):
|
|||
wf.write(preloader)
|
||||
print(f"Successfully extracted preloader for this device to: {pfilename}")
|
||||
return preloader
|
||||
except:
|
||||
except Exception as err:
|
||||
self.error(str(err))
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
|
@ -426,7 +434,7 @@ class Main(metaclass=LogBase):
|
|||
return
|
||||
self.close()
|
||||
elif cmd == "peek":
|
||||
addr = getint(self.args.offset)
|
||||
addr = getint(self.args.address)
|
||||
length = getint(self.args.length)
|
||||
if self.args.preloader is not None:
|
||||
preloader = self.args.preloader
|
||||
|
@ -608,7 +616,7 @@ class Main(metaclass=LogBase):
|
|||
if self.args.ptype is not None:
|
||||
ptype = self.args.ptype
|
||||
plt.runpayload(filename=payloadfile)
|
||||
mtk.port.close()
|
||||
mtk.port.close(reset=True)
|
||||
self.close()
|
||||
elif cmd == "gettargetconfig":
|
||||
if mtk.preloader.init():
|
||||
|
@ -620,10 +628,16 @@ class Main(metaclass=LogBase):
|
|||
# DA / FLash commands start here
|
||||
|
||||
mtk.port.cdc.connected=mtk.port.cdc.connect()
|
||||
if mtk.port.cdc.connected:
|
||||
if mtk.port.cdc.connected and os.path.exists(".state"):
|
||||
info=mtk.daloader.reinit()
|
||||
else:
|
||||
preloader = self.args.preloader
|
||||
if os.path.exists("logs"):
|
||||
shutil.rmtree("logs", ignore_errors=False, onerror=None)
|
||||
os.mkdir("logs")
|
||||
try:
|
||||
preloader = self.args.preloader
|
||||
except:
|
||||
preloader = None
|
||||
if mtk.preloader.init():
|
||||
if mtk.config.target_config["daa"]:
|
||||
mtk = mtk.bypass_security()
|
||||
|
@ -636,10 +650,12 @@ class Main(metaclass=LogBase):
|
|||
else:
|
||||
self.info("Device is unprotected.")
|
||||
if mtk.config.is_brom:
|
||||
#mtk = mtk.bypass_security()
|
||||
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(mtk)
|
||||
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
|
||||
|
@ -809,8 +825,8 @@ class Main(metaclass=LogBase):
|
|||
print(f"Detected partition: {partition.name}")
|
||||
if partition.name in ["userdata2", "userdata"]:
|
||||
data = mtk.daloader.readflash(
|
||||
addr=(
|
||||
partition.sector + partition.sectors) * mtk.daloader.daconfig.pagesize - 0x4000,
|
||||
addr=(partition.sector + partition.sectors) *
|
||||
mtk.daloader.daconfig.pagesize - 0x4000,
|
||||
length=0x4000, filename="", parttype="user", display=False)
|
||||
else:
|
||||
data = mtk.daloader.readflash(addr=partition.sector * mtk.daloader.daconfig.pagesize,
|
||||
|
@ -846,7 +862,7 @@ class Main(metaclass=LogBase):
|
|||
mtk.daloader.writeflash(addr=0,
|
||||
length=os.stat(partfilename).st_size,
|
||||
filename=partfilename,
|
||||
partitionname=partition, parttype=parttype)
|
||||
parttype=parttype)
|
||||
continue
|
||||
res = mtk.daloader.detect_partition(self.args, partition, parttype)
|
||||
if res[0]:
|
||||
|
@ -854,7 +870,7 @@ class Main(metaclass=LogBase):
|
|||
if mtk.daloader.writeflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
|
||||
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
|
||||
filename=partfilename,
|
||||
partitionname=partition, parttype=parttype):
|
||||
parttype=parttype):
|
||||
print(
|
||||
f"Wrote {partfilename} to sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
|
@ -902,7 +918,7 @@ class Main(metaclass=LogBase):
|
|||
if mtk.daloader.writeflash(addr=0,
|
||||
length=os.stat(partfilename).st_size,
|
||||
filename=partfilename,
|
||||
partitionname=partition, parttype=parttype):
|
||||
parttype=parttype):
|
||||
print(f"Wrote {partition} to sector {str(0)}")
|
||||
else:
|
||||
print(f"Failed to write {partition} to sector {str(0)}")
|
||||
|
@ -913,7 +929,7 @@ class Main(metaclass=LogBase):
|
|||
if mtk.daloader.writeflash(addr=rpartition.sector * mtk.daloader.daconfig.pagesize,
|
||||
length=rpartition.sectors * mtk.daloader.daconfig.pagesize,
|
||||
filename=partfilename,
|
||||
partitionname=partition, parttype=parttype):
|
||||
parttype=parttype):
|
||||
print(
|
||||
f"Wrote {partfilename} to sector {str(rpartition.sector)} with " +
|
||||
f"sector count {str(rpartition.sectors)}.")
|
||||
|
@ -968,6 +984,54 @@ class Main(metaclass=LogBase):
|
|||
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
|
||||
for rpartition in res[1]:
|
||||
self.info(rpartition.name)
|
||||
self.close()
|
||||
elif cmd == "es":
|
||||
partitionname = self.args.partitionname
|
||||
parttype = self.args.parttype
|
||||
sectors = getint(self.args.sectors)
|
||||
if self.args.sectors is None:
|
||||
self.error("Sector count is missing. Usage: es [partname] [sector count]")
|
||||
self.close()
|
||||
partitions = partitionname.split(",")
|
||||
if parttype == "user" or parttype is None:
|
||||
i = 0
|
||||
for partition in partitions:
|
||||
i += 1
|
||||
res = mtk.daloader.detect_partition(self.args, partition, parttype)
|
||||
if res[0]:
|
||||
rpartition = res[1]
|
||||
rsectors=min(sectors*mtk.daloader.daconfig.pagesize,
|
||||
rpartition.sectors * 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 * mtk.daloader.daconfig.pagesize
|
||||
wsize=min(sectorsize,0x200000)
|
||||
if mtk.daloader.writeflash(addr=sector * 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//mtk.daloader.daconfig.pagesize)
|
||||
sector += (wsize//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:
|
||||
|
@ -998,9 +1062,49 @@ class Main(metaclass=LogBase):
|
|||
os.remove(".state")
|
||||
mtk.daloader.close()
|
||||
self.close()
|
||||
print("Reset command was sent. Disconnect usb cable to power off.")
|
||||
elif cmd == "xflash":
|
||||
subcmd = args.subcmd
|
||||
if subcmd is None:
|
||||
print("Available xflash cmds are: [peek, poke, generatekeys, unlock, rpmb]")
|
||||
return
|
||||
if subcmd == "peek":
|
||||
addr = getint(self.args.address)
|
||||
length = getint(self.args.length)
|
||||
data=mtk.daloader.peek(addr=addr,length=length)
|
||||
if data!=b"":
|
||||
if self.args.filename is not None:
|
||||
filename = self.args.filename
|
||||
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")
|
||||
elif subcmd == "poke":
|
||||
addr = getint(self.args.address)
|
||||
if self.args.filename is not None:
|
||||
if os.path.exists(self.args.filename):
|
||||
data=open(self.args.filename,"rb").read()
|
||||
else:
|
||||
if "0x" in self.args.data:
|
||||
data = pack("<I",int(self.args.data,16))
|
||||
else:
|
||||
data = bytes.fromhex(self.args.data)
|
||||
if mtk.daloader.poke(addr=addr, data=data):
|
||||
self.info(f"Successfully wrote data to {hex(addr)}, length {hex(len(data))}")
|
||||
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 xflash rpmb cmds are: [r w]')
|
||||
if rpmb_subcmd == "r":
|
||||
mtk.daloader.read_rpmb(args.filename)
|
||||
self.close()
|
||||
|
||||
|
||||
info = "MTK Flash/Exploit Client V1.43 (c) B.Kerler 2018-2021"
|
||||
info = "MTK Flash/Exploit Client V1.50 (c) B.Kerler 2018-2021"
|
||||
|
||||
cmds = {
|
||||
"printgpt": "Print GPT Table information",
|
||||
|
@ -1013,6 +1117,7 @@ cmds = {
|
|||
"wf": "Write flash from filename",
|
||||
"wl": "Write partitions from directory path to flash",
|
||||
"e": "Erase partition",
|
||||
"es": "Erase partition with sector count",
|
||||
"footer": "Read crypto footer from flash",
|
||||
"reset": "Send mtk reset command",
|
||||
"dumpbrom": "Try to dump the bootrom",
|
||||
|
@ -1023,7 +1128,8 @@ cmds = {
|
|||
"gettargetconfig": "Get target config (sbc, daa, etc.)",
|
||||
"peek": "Read memory in patched preloader mode",
|
||||
"stage": "Run stage2 payload via boot rom mode (kamakiri)",
|
||||
"plstage": "Run stage2 payload via preloader mode (send_da)"
|
||||
"plstage": "Run stage2 payload via preloader mode (send_da)",
|
||||
"xflash" : "Run da xflash special commands"
|
||||
}
|
||||
|
||||
|
||||
|
@ -1037,13 +1143,14 @@ def showcommands():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(info)
|
||||
print("")
|
||||
parser = argparse.ArgumentParser(description=info)
|
||||
subparsers = parser.add_subparsers(dest="cmd",
|
||||
help='Valid commands are: \n' +
|
||||
'printgpt, gpt, r, rl, rf, rs, w, wf, wl, e, footer, reset, dumpbrom, \n' +
|
||||
'dumppreloader, payload, crash, brute, gettargetconfig, peek, \n' +
|
||||
'stage, plstage \n')
|
||||
'printgpt, gpt, r, rl, rf, rs, w, wf, wl, e, es, footer, reset, \n' +
|
||||
'dumpbrom, dumppreloader, payload, crash, brute, gettargetconfig, \n' +
|
||||
'peek, stage, plstage, da \n')
|
||||
|
||||
parser_printgpt = subparsers.add_parser("printgpt", help="Print GPT Table information")
|
||||
parser_gpt = subparsers.add_parser("gpt", help="Save gpt table to given directory")
|
||||
|
@ -1055,6 +1162,7 @@ if __name__ == '__main__':
|
|||
parser_wf = subparsers.add_parser("wf", help="Write flash from filename")
|
||||
parser_wl = subparsers.add_parser("wl", help="Write partitions from directory path to flash")
|
||||
parser_e = subparsers.add_parser("e", help="Erase partition")
|
||||
parser_es = subparsers.add_parser("es", help="Erase partition 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")
|
||||
|
@ -1070,6 +1178,31 @@ if __name__ == '__main__':
|
|||
parser_stage = subparsers.add_parser("stage", help="Run stage2 payload via boot rom mode (kamakiri)")
|
||||
parser_plstage = subparsers.add_parser("plstage", help="Run stage2 payload via preloader mode (send_da)")
|
||||
|
||||
parser_xflash = subparsers.add_parser("xflash", help="Run xflash special commands")
|
||||
da_cmds = parser_xflash.add_subparsers(dest='subcmd', help='Commands: peek poke keys unlock')
|
||||
da_peek = da_cmds.add_parser("peek", help="Read memory")
|
||||
da_poke = da_cmds.add_parser("poke", help="Write memory")
|
||||
da_keys = da_cmds.add_parser("generatekeys", help="Generate keys")
|
||||
da_unlock = da_cmds.add_parser("seccfg", help="Unlock device / Configure seccfg")
|
||||
da_rpmb = da_cmds.add_parser("rpmb", help="RPMB Tools")
|
||||
|
||||
da_rpmb_cmds = da_rpmb.add_subparsers(dest='rpmb_subcmd', help='Commands: r w')
|
||||
da_rpmb_r = da_rpmb_cmds.add_parser("r", help="Read rpmb")
|
||||
da_rpmb_r.add_argument('--filename', type=str, help="Filename to write data into")
|
||||
|
||||
da_rpmb_w = da_rpmb_cmds.add_parser("w", help="Write rpmb")
|
||||
da_rpmb_w.add_argument('--filename', type=str, help="Filename to write from")
|
||||
|
||||
da_peek.add_argument('address', type=str, help="Address to read from (hex value)")
|
||||
da_peek.add_argument('length', type=str, help="Length to read")
|
||||
da_peek.add_argument('--filename', type=str, help="Filename to write data into")
|
||||
|
||||
da_poke.add_argument('address', type=str, help="Address to read from (hex value)")
|
||||
da_poke.add_argument('data', type=str, help="Data to write")
|
||||
da_poke.add_argument('--filename', type=str, help="Filename to read data from")
|
||||
|
||||
da_unlock.add_argument('flag', type=str, help="Needed flag (unlock,lock)")
|
||||
|
||||
parser_printgpt.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
|
||||
parser_printgpt.add_argument('--vid', type=str, help='Set usb vendor id used for MTK Preloader')
|
||||
parser_printgpt.add_argument('--pid', type=str, help='Set usb product id used for MTK Preloader')
|
||||
|
@ -1345,6 +1478,35 @@ if __name__ == '__main__':
|
|||
parser_e.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
|
||||
parser_e.add_argument('--socid', help='Read Soc ID')
|
||||
|
||||
parser_es.add_argument('partitionname', help='Partitionname to erase from flash')
|
||||
parser_es.add_argument('sectors', help='Sectors to erase')
|
||||
parser_es.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
|
||||
parser_es.add_argument('--vid', type=str, help='Set usb vendor id used for MTK Preloader')
|
||||
parser_es.add_argument('--pid', type=str, help='Set usb product id used for MTK Preloader')
|
||||
parser_es.add_argument('--sectorsize', default='0x200', help='Set default sector size')
|
||||
parser_es.add_argument('--debugmode', action='store_true', default=False, help='Enable verbose mode')
|
||||
parser_es.add_argument('--gpt-num-part-entries', default='0', help='Set GPT entry count')
|
||||
parser_es.add_argument('--gpt-part-entry-size', default='0', help='Set GPT entry size')
|
||||
parser_es.add_argument('--gpt-part-entry-start-lba', default='0', help='Set GPT entry start lba sector')
|
||||
parser_es.add_argument('--skip', help='Skip reading partition with names "partname1,partname2,etc."')
|
||||
parser_es.add_argument('--skipwdt', help='Skip wdt init')
|
||||
parser_es.add_argument('--wdt', help='Set a specific watchdog addr')
|
||||
parser_es.add_argument('--mode', help='Set a crash mode (0=dasend1,1=dasend2,2=daread)')
|
||||
parser_es.add_argument('--var1', help='Set kamakiri specific var1 value')
|
||||
parser_es.add_argument('--uart_addr', help='Set payload uart_addr value')
|
||||
parser_es.add_argument('--da_addr', help='Set a specific da payload addr')
|
||||
parser_es.add_argument('--brom_addr', help='Set a specific brom payload addr')
|
||||
parser_es.add_argument('--ptype',
|
||||
help='Set the payload type ( "amonet","kamakiri","kamakiri2", kamakiri2/da used by default)')
|
||||
parser_es.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
parser_es.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
|
||||
parser_es.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_es.add_argument('--filename', help='Optional filename')
|
||||
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_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')
|
||||
|
@ -1456,7 +1618,7 @@ if __name__ == '__main__':
|
|||
parser_gettargetconfig.add_argument('--debugmode', action='store_true', default=False, help='Enable verbose mode')
|
||||
parser_gettargetconfig.add_argument('--socid', help='Read Soc ID')
|
||||
|
||||
parser_peek.add_argument('offset', help='Offset to read from memory')
|
||||
parser_peek.add_argument('address', help='Address to read from memory')
|
||||
parser_peek.add_argument('length', help='Bytes to read from memory')
|
||||
parser_peek.add_argument('--filename', help='Optional filename to write dumped data')
|
||||
parser_peek.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
|
||||
|
@ -1520,6 +1682,19 @@ if __name__ == '__main__':
|
|||
parser_plstage.add_argument('--socid', help='Read Soc ID')
|
||||
parser_plstage.add_argument('--startpartition', help='Option for plstage - Boot to (lk, tee1)')
|
||||
|
||||
parser_printgpt.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_footer.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_e.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_es.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_wl.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_wf.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_w.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_rs.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_rf.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_rl.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_gpt.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
parser_r.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
|
||||
|
||||
args = parser.parse_args()
|
||||
cmd = args.cmd
|
||||
if cmd not in cmds:
|
||||
|
|
|
@ -105,6 +105,7 @@ class Port(metaclass=LogBase):
|
|||
resp = b""
|
||||
dlen = len(value)
|
||||
wr = self.usbwrite(value)
|
||||
time.sleep(0.05)
|
||||
if wr:
|
||||
if nocmd:
|
||||
cmdrsp = self.usbread(bytestoread)
|
||||
|
|
|
@ -6,6 +6,7 @@ import os
|
|||
from struct import unpack
|
||||
from mtkclient.Library.utils import LogBase, read_object, logsetup
|
||||
from mtkclient.config.payloads import pathconfig
|
||||
from mtkclient.config.brom_config import damodes
|
||||
|
||||
class Storage:
|
||||
MTK_DA_HW_STORAGE_NOR = 0
|
||||
|
@ -108,9 +109,10 @@ class DAconfig(metaclass=LogBase):
|
|||
self.readsize = 0
|
||||
self.pagesize = 512
|
||||
self.da = None
|
||||
self.da2 = None
|
||||
self.dasetup = {}
|
||||
self.loader = loader
|
||||
self.extract_emi(preloader, self.mtk.config.chipconfig.damode)
|
||||
self.extract_emi(preloader)
|
||||
|
||||
if loader is None:
|
||||
loaders = []
|
||||
|
@ -126,10 +128,36 @@ class DAconfig(metaclass=LogBase):
|
|||
else:
|
||||
self.parse_da_loader(loader)
|
||||
|
||||
def extract_emi(self, preloader=None, legacy=False) -> bytearray:
|
||||
def m_extract_emi(self, data):
|
||||
idx = data.find(b"\x4D\x4D\x4D\x01\x38\x00\x00\x00")
|
||||
siglen = 0
|
||||
if idx != -1:
|
||||
data = data[idx:]
|
||||
mlen = unpack("<I", data[0x20:0x20 + 4])[0]
|
||||
siglen = unpack("<I", data[0x2C:0x2C + 4])[0]
|
||||
data = data[:mlen]
|
||||
|
||||
idx = data.find(b"MTK_BLOADER_INFO")
|
||||
if idx == -1:
|
||||
return None
|
||||
elif idx == 0:
|
||||
return data
|
||||
emi = data[idx:-siglen]
|
||||
rlen = len(emi) - 4
|
||||
if len(emi) > 4:
|
||||
val = unpack("<I", emi[-4:])[0]
|
||||
if val == rlen:
|
||||
emi = emi[:rlen]
|
||||
if not self.config.chipconfig.damode==damodes.XFLASH:
|
||||
if emi.find(b"MTK_BIN")!=-1:
|
||||
emi=emi[emi.find(b"MTK_BIN")+0xC:]
|
||||
return emi
|
||||
return None
|
||||
|
||||
def extract_emi(self, preloader=None) -> bytearray:
|
||||
if preloader is None:
|
||||
self.emi = None
|
||||
return
|
||||
return b""
|
||||
if isinstance(preloader, bytearray) or isinstance(preloader, bytes):
|
||||
data = bytearray(preloader)
|
||||
elif isinstance(preloader, str):
|
||||
|
@ -139,25 +167,7 @@ class DAconfig(metaclass=LogBase):
|
|||
else:
|
||||
assert "Preloader :"+preloader+" doesn't exist. Aborting."
|
||||
exit(1)
|
||||
if legacy:
|
||||
idx = data.rfind(b"MTK_BIN")
|
||||
if idx == -1:
|
||||
self.emi = None
|
||||
return
|
||||
dramdata = data[idx:][0xC:][:-0x128]
|
||||
self.emi = dramdata
|
||||
return
|
||||
else:
|
||||
idx = data.rfind(b"MTK_BLOADER_INFO_v")
|
||||
if idx != -1:
|
||||
emi = data[idx:]
|
||||
count = unpack("<I", emi[0x6C:0x70])[0]
|
||||
size = (count * 0xB0) + 0x70
|
||||
emi = emi[:size]
|
||||
self.emi = emi
|
||||
return
|
||||
self.emi = None
|
||||
return
|
||||
self.emi = self.m_extract_emi(data)
|
||||
|
||||
def parse_da_loader(self, loader):
|
||||
if not "MTK_AllInOne_DA" in loader:
|
||||
|
|
|
@ -64,11 +64,13 @@ class hwcrypto(metaclass=LogBase):
|
|||
return self.gcpu.aes_read_cbc(addr=addr, encrypt=encrypt)
|
||||
elif btype == "dxcc":
|
||||
if mode == "fde":
|
||||
return self.dxcc.generate_fde()
|
||||
return self.dxcc.generate_rpmb(1)
|
||||
elif mode == "rpmb2":
|
||||
return self.dxcc.generate_rpmb(2)
|
||||
elif mode == "rpmb":
|
||||
return self.dxcc.generate_rpmb()
|
||||
elif mode == "itrustee-fde":
|
||||
return self.dxcc.generate_itrustee_fde()
|
||||
elif mode == "itrustee":
|
||||
return self.dxcc.generate_itrustee_fbe()
|
||||
elif mode == "prov":
|
||||
return self.dxcc.generate_provision_key()
|
||||
elif mode == "sha256":
|
||||
|
|
|
@ -838,13 +838,14 @@ SEP_MAX_CTX_SIZE (max(sizeof(struct sep_ctx_rc4), \
|
|||
"""
|
||||
|
||||
|
||||
def HW_DESC_INIT():
|
||||
return [0, 0, 0, 0, 0, 0]
|
||||
def hw_desc_init():
|
||||
res = [0, 0, 0, 0, 0, 0]
|
||||
return res
|
||||
|
||||
|
||||
def BITMASK(mask_size):
|
||||
def bitmask(mask_size):
|
||||
if mask_size < 32:
|
||||
return (1 << (mask_size)) - 1
|
||||
return (1 << mask_size) - 1
|
||||
else:
|
||||
return 0xFFFFFFFF
|
||||
|
||||
|
@ -854,37 +855,37 @@ def tovalue(value, bitsize, shift):
|
|||
return v << shift
|
||||
|
||||
|
||||
def HW_DESC_SET_CIPHER_MODE(pDesc, cipherMode):
|
||||
def hw_desc_set_cipher_mode(pDesc, cipherMode):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_MODE"]
|
||||
pDesc[4] |= tovalue(cipherMode, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_CIPHER_CONFIG0(pDesc, cipherConfig):
|
||||
def hw_desc_set_cipher_config0(pDesc, cipherConfig):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_CONF0"]
|
||||
pDesc[4] |= tovalue(cipherConfig, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_CIPHER_CONFIG1(pDesc, cipherConfig):
|
||||
def hw_desc_set_cipher_config1(pDesc, cipherConfig):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_CONF1"]
|
||||
pDesc[4] |= tovalue(cipherConfig, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_SETUP_MODE(pDesc, setupMode):
|
||||
def hw_desc_set_setup_mode(pDesc, setupMode):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["SETUP_OPERATION"]
|
||||
pDesc[4] |= tovalue(setupMode, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_FLOW_MODE(pDesc, flowMode):
|
||||
def hw_desc_set_flow_mode(pDesc, flowMode):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["DATA_FLOW_MODE"]
|
||||
pDesc[4] |= tovalue(flowMode, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_DOUT_SRAM(pDesc, doutAdr, doutSize):
|
||||
def hw_desc_set_dout_sram(pDesc, doutAdr, doutSize):
|
||||
v = DSCRPTR["DSCRPTR_QUEUE0_WORD2"]
|
||||
shift, bitsize = v[1], v[2]
|
||||
pDesc[2] |= tovalue((doutAdr & 0xFFFFFFFF), bitsize, shift)
|
||||
|
@ -895,7 +896,7 @@ def HW_DESC_SET_DOUT_SRAM(pDesc, doutAdr, doutSize):
|
|||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_DOUT_DLLI(pDesc, doutAdr, doutSize, axiNs, lastind):
|
||||
def hw_desc_set_dout_dlli(pDesc, doutAdr, doutSize, axiNs, lastind):
|
||||
v = DSCRPTR["DSCRPTR_QUEUE0_WORD2"]
|
||||
shift, bitsize = v[1], v[2]
|
||||
pDesc[2] |= tovalue((doutAdr & 0xFFFFFFFF), bitsize, shift)
|
||||
|
@ -912,13 +913,13 @@ def HW_DESC_SET_DOUT_DLLI(pDesc, doutAdr, doutSize, axiNs, lastind):
|
|||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_KEY_SIZE_AES(pDesc, keySize):
|
||||
def hw_desc_set_key_size_aes(pDesc, keySize):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["KEY_SIZE"]
|
||||
pDesc[4] |= tovalue(((keySize >> 3) - 2), bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_DIN_SRAM(pDesc, dinAdr, dinSize):
|
||||
def hw_desc_set_din_sram(pDesc, dinAdr, dinSize):
|
||||
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
|
||||
shift, bitsize = v[1], v[2]
|
||||
pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
|
||||
|
@ -929,7 +930,7 @@ def HW_DESC_SET_DIN_SRAM(pDesc, dinAdr, dinSize):
|
|||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_DIN_CONST(pDesc, val, dinSize):
|
||||
def hw_desc_set_din_const(pDesc, val, dinSize):
|
||||
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
|
||||
shift, bitsize = v[1], v[2]
|
||||
pDesc[0] |= tovalue(val & 0xFFFFFFFF, bitsize, shift)
|
||||
|
@ -942,12 +943,13 @@ def HW_DESC_SET_DIN_CONST(pDesc, val, dinSize):
|
|||
return pDesc
|
||||
|
||||
|
||||
def HW_DESC_SET_CIPHER_DO(pDesc, cipherDo):
|
||||
def hw_desc_set_cipher_do(pDesc, cipherDo):
|
||||
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_DO"]
|
||||
pDesc[4] |= tovalue(cipherDo, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
def HW_DESC_SET_DIN_NODMA(pDesc, dinAdr, dinSize):
|
||||
|
||||
def hw_desc_set_din_nodma(pDesc, dinAdr, dinSize):
|
||||
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
|
||||
shift, bitsize = v[1], v[2]
|
||||
pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
|
||||
|
@ -957,7 +959,8 @@ def HW_DESC_SET_DIN_NODMA(pDesc, dinAdr, dinSize):
|
|||
pDesc[1] |= tovalue(dinSize, bitsize, shift)
|
||||
return pDesc
|
||||
|
||||
def HW_DESC_SET_DIN_TYPE(pDesc, dmaMode, dinAdr, dinSize, axiId, axiNs):
|
||||
|
||||
def hw_desc_set_din_type(pDesc, dmaMode, dinAdr, dinSize, axiId, axiNs):
|
||||
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
|
||||
shift, bitsize = v[1], v[2]
|
||||
pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
|
||||
|
@ -1009,7 +1012,7 @@ class dxcc(metaclass=LogBase):
|
|||
DX_DSCRPTR_QUEUE0_WORD4 = 0xE90
|
||||
DX_DSCRPTR_QUEUE0_WORD5 = 0xE94
|
||||
DX_DSCRPTR_QUEUE0_CONTENT = 0xE9C
|
||||
DX_HOST_SEP_HOST_GPR0 = 0xA80 # DX_HOST_SEP_HOST_GPR0_REG_OFFSET
|
||||
DX_HOST_SEP_HOST_GPR0 = 0xA80 # DX_HOST_SEP_HOST_GPR0_REG_OFFSET
|
||||
DX_HOST_SEP_HOST_GPR1 = 0xA88
|
||||
DX_HOST_SEP_HOST_GPR2 = 0xA90
|
||||
DX_HOST_SEP_HOST_GPR3 = 0xA9C
|
||||
|
@ -1023,16 +1026,15 @@ class dxcc(metaclass=LogBase):
|
|||
value = self.read32(self.dxcc_base + self.DX_HOST_IRR)
|
||||
if value != 0:
|
||||
return value
|
||||
return None
|
||||
|
||||
def SaSi_PalDmaUnMap(self, value1):
|
||||
def sasi_paldmaunmap(self, value1):
|
||||
return
|
||||
|
||||
def SaSi_PalDmaMap(self, value1):
|
||||
def sasi_paldmamap(self, value1):
|
||||
# value2=value1
|
||||
return value1
|
||||
|
||||
def SaSi_SB_AddDescSequence(self, data):
|
||||
def sasi_sb_adddescsequence(self, data):
|
||||
while True:
|
||||
if self.read32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_CONTENT) << 0x1C != 0:
|
||||
break
|
||||
|
@ -1062,34 +1064,33 @@ class dxcc(metaclass=LogBase):
|
|||
res = self.write32(0x10001088, 0x8000000)
|
||||
return res
|
||||
|
||||
def generate_fde(self):
|
||||
fde_ikey = b"SQNC!LFZ"
|
||||
fde_salt = b"TBTJ"
|
||||
self.tzcc_clk(1)
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
fdekey = self.SBROM_KeyDerivation(1, fde_ikey, fde_salt, 0x10, dstaddr)
|
||||
self.tzcc_clk(0)
|
||||
return fdekey
|
||||
|
||||
def generate_itrustee_fde(self, key_sz=32):
|
||||
def generate_itrustee_fbe(self, key_sz=32):
|
||||
fdekey = b""
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
self.tzcc_clk(1)
|
||||
for ctr in range(0, key_sz // 16):
|
||||
itrustee = b"TrustedCorekeymaster" + b"\x07" * 0x10
|
||||
seed = itrustee + pack("<B", ctr)
|
||||
paddr=self.SBROM_AesCmac(1,0x0,seed,0x0,len(seed),dstaddr)
|
||||
paddr = self.SBROM_AesCmac(1, 0x0, seed, 0x0, len(seed), dstaddr)
|
||||
for field in self.read32(paddr + 0x108, 4):
|
||||
fdekey+=pack("<I", field)
|
||||
fdekey += pack("<I", field)
|
||||
self.tzcc_clk(0)
|
||||
return fdekey
|
||||
|
||||
def generate_rpmb(self):
|
||||
rpmb_ikey = b"RPMB KEY"
|
||||
rpmb_salt = b"SASI"
|
||||
def generate_rpmb(self, level=0):
|
||||
rpmb_ikey = bytearray(b"RPMB KEY")
|
||||
rpmb_salt = bytearray(b"SASI")
|
||||
for i in range(len(rpmb_ikey)):
|
||||
rpmb_ikey[i] = rpmb_ikey[i] + level
|
||||
for i in range(len(rpmb_salt)):
|
||||
rpmb_salt[i] = rpmb_salt[i] + level
|
||||
|
||||
keylength = 0x20
|
||||
if level > 0:
|
||||
keylength = 0x10
|
||||
self.tzcc_clk(1)
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
rpmbkey = self.SBROM_KeyDerivation(1, rpmb_ikey, rpmb_salt, 0x20, dstaddr)
|
||||
rpmbkey = self.SBROM_KeyDerivation(1, rpmb_ikey, rpmb_salt, keylength, dstaddr)
|
||||
self.tzcc_clk(0)
|
||||
return rpmbkey
|
||||
|
||||
|
@ -1105,8 +1106,8 @@ class dxcc(metaclass=LogBase):
|
|||
|
||||
def generate_sha256(self, data):
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
self.SBROM_SHA256(buffer=data,destaddr=dstaddr)
|
||||
result=bytearray()
|
||||
self.sbrom_sha256(buffer=data, destaddr=dstaddr)
|
||||
result = bytearray()
|
||||
for field in self.read32(dstaddr, 8):
|
||||
result.extend(pack("<I", field))
|
||||
return result
|
||||
|
@ -1167,14 +1168,14 @@ class dxcc(metaclass=LogBase):
|
|||
def SB_HalWaitDescCompletion(self, destptr):
|
||||
data = []
|
||||
self.SB_HalClearInterruptBit()
|
||||
val = self.SaSi_PalDmaMap(0)
|
||||
val = self.sasi_paldmamap(0)
|
||||
data.append(0x0) # 0
|
||||
data.append(0x8000011) # 1 #DIN_DMA|DOUT_DMA|DIN_CONST
|
||||
data.append(destptr) # 2
|
||||
data.append(0x8000012) # 3
|
||||
data.append(0x100) # 4
|
||||
data.append((destptr >> 32) << 16) # 5
|
||||
self.SaSi_SB_AddDescSequence(data)
|
||||
self.sasi_sb_adddescsequence(data)
|
||||
while True:
|
||||
if self.SB_CryptoWait() & 4 != 0:
|
||||
break
|
||||
|
@ -1184,7 +1185,7 @@ class dxcc(metaclass=LogBase):
|
|||
break
|
||||
if value == 1:
|
||||
self.SB_HalClearInterruptBit()
|
||||
self.SaSi_PalDmaUnMap(val)
|
||||
self.sasi_paldmaunmap(val)
|
||||
return 0
|
||||
else:
|
||||
return 0xF6000001
|
||||
|
@ -1199,50 +1200,52 @@ class dxcc(metaclass=LogBase):
|
|||
keySizeInBytes = 0x10 # SEP_AES_128_BIT_KEY_SIZE
|
||||
self.SB_HalInit()
|
||||
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_cipher_mode.SEP_CIPHER_CMAC)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG0(desc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
|
||||
desc = HW_DESC_SET_KEY_SIZE_AES(desc, keySizeInBytes)
|
||||
# desc = HW_DESC_SET_DIN_SRAM(desc, ivSramAddr, AES_IV_COUNTER_SIZE_IN_BYTES)
|
||||
desc = HW_DESC_SET_DIN_CONST(desc, 0, AES_IV_COUNTER_SIZE_IN_BYTES)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_DIN_to_AES)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_LOAD_STATE0)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
pdesc = hw_desc_init()
|
||||
pdesc = hw_desc_set_cipher_mode(pdesc, sep_cipher_mode.SEP_CIPHER_CMAC) # desc[4]=0x1C00
|
||||
pdesc = hw_desc_set_cipher_config0(pdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
|
||||
pdesc = hw_desc_set_key_size_aes(pdesc, keySizeInBytes) # desc[4]=0x801C00
|
||||
# pdesc = hw_desc_set_din_sram(pdesc, ivSramAddr, AES_IV_COUNTER_SIZE_IN_BYTES)
|
||||
pdesc = hw_desc_set_din_const(pdesc, 0, AES_IV_COUNTER_SIZE_IN_BYTES) # desc[1]=0x8000041
|
||||
pdesc = hw_desc_set_flow_mode(pdesc, FlowMode.S_DIN_to_AES) # desc[4]=0x801C20
|
||||
pdesc = hw_desc_set_setup_mode(pdesc, SetupOp.SETUP_LOAD_STATE0) # desc[4]=0x1801C20
|
||||
self.sasi_sb_adddescsequence(pdesc)
|
||||
|
||||
# Load key
|
||||
desc = HW_DESC_INIT()
|
||||
mdesc = hw_desc_init()
|
||||
if aesKeyType == HwCryptoKey.USER_KEY:
|
||||
desc = HW_DESC_SET_DIN_SRAM(desc, pInternalKey, AES_Key128Bits_SIZE_IN_BYTES)
|
||||
desc = HW_DESC_SET_CIPHER_DO(desc, aesKeyType)
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_cipher_mode.SEP_CIPHER_CMAC)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG0(desc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
|
||||
desc = HW_DESC_SET_KEY_SIZE_AES(desc, keySizeInBytes)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_DIN_to_AES)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_LOAD_KEY0)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
mdesc = hw_desc_set_din_sram(mdesc, pInternalKey, AES_Key128Bits_SIZE_IN_BYTES)
|
||||
mdesc = hw_desc_set_cipher_do(mdesc, aesKeyType) # desc[4]=0x8000
|
||||
mdesc = hw_desc_set_cipher_mode(mdesc, sep_cipher_mode.SEP_CIPHER_CMAC) # desc[4]=0x9C00
|
||||
mdesc = hw_desc_set_cipher_config0(mdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
|
||||
mdesc = hw_desc_set_key_size_aes(mdesc, keySizeInBytes) # desc[4]=0x809C00
|
||||
mdesc = hw_desc_set_flow_mode(mdesc, FlowMode.S_DIN_to_AES) # desc[4]=0x809C20
|
||||
mdesc = hw_desc_set_setup_mode(mdesc, SetupOp.SETUP_LOAD_KEY0) # desc[4]=0x4809C20
|
||||
self.sasi_sb_adddescsequence(mdesc)
|
||||
|
||||
# Process input data
|
||||
desc = HW_DESC_INIT()
|
||||
rdesc = hw_desc_init()
|
||||
if dmaMode == DmaMode.DMA_SRAM:
|
||||
desc = HW_DESC_SET_DIN_SRAM(desc, pDataIn, blockSize)
|
||||
rdesc = hw_desc_set_din_sram(rdesc, pDataIn, blockSize)
|
||||
else:
|
||||
desc = HW_DESC_SET_DIN_TYPE(desc, DmaMode.DMA_DLLI, pDataIn, blockSize, SB_AXI_ID, AXI_SECURE)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.DIN_AES_DOUT)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
rdesc = hw_desc_set_din_type(rdesc, DmaMode.DMA_DLLI, pDataIn, blockSize, SB_AXI_ID,
|
||||
AXI_SECURE) # desc[1]=0x3E, desc[0]=0x200E18
|
||||
rdesc = hw_desc_set_flow_mode(rdesc, FlowMode.DIN_AES_DOUT) # desc[4]=1
|
||||
self.sasi_sb_adddescsequence(rdesc)
|
||||
|
||||
if aesKeyType != HwCryptoKey.PROVISIONING_KEY:
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_cipher_mode.SEP_CIPHER_CMAC)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG0(desc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_WRITE_STATE0)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_AES_to_DOUT)
|
||||
xdesc = hw_desc_init()
|
||||
xdesc = hw_desc_set_cipher_mode(xdesc, sep_cipher_mode.SEP_CIPHER_CMAC) # desc[4]=0x1C00
|
||||
xdesc = hw_desc_set_cipher_config0(xdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
|
||||
xdesc = hw_desc_set_setup_mode(xdesc, SetupOp.SETUP_WRITE_STATE0) # desc[4]=0x8001C00
|
||||
xdesc = hw_desc_set_flow_mode(xdesc, FlowMode.S_AES_to_DOUT) # desc[4]=0x8001C26
|
||||
if dmaMode == DmaMode.DMA_SRAM:
|
||||
desc = HW_DESC_SET_DOUT_SRAM(desc, pInternalKey, AES_BLOCK_SIZE_IN_BYTES)
|
||||
xdesc = hw_desc_set_dout_sram(xdesc, pInternalKey, AES_BLOCK_SIZE_IN_BYTES)
|
||||
else:
|
||||
desc = HW_DESC_SET_DOUT_DLLI(desc, pInternalKey, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID, 0)
|
||||
#desc = HW_DESC_SET_DIN_SRAM(desc, 0, 0)
|
||||
desc = HW_DESC_SET_DIN_NODMA(desc, 0, 0)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
xdesc = hw_desc_set_dout_dlli(xdesc, pInternalKey, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID,
|
||||
0) # desc[2]=0x200E08, desc[3]=0x42
|
||||
# xdesc = hw_desc_set_din_sram(xdesc, 0, 0)
|
||||
xdesc = hw_desc_set_din_nodma(xdesc, 0, 0)
|
||||
self.sasi_sb_adddescsequence(xdesc)
|
||||
return self.SB_HalWaitDescCompletion(pCMacResult) == 0
|
||||
|
||||
def mtee_decrypt(self, data):
|
||||
|
@ -1256,69 +1259,69 @@ class dxcc(metaclass=LogBase):
|
|||
ctr = Counter.new(128, initial_value=bytes_to_long(iv))
|
||||
return AES.new(key=key, counter=ctr, mode=AES.MODE_CTR).decrypt(data)
|
||||
|
||||
def SBROM_SHA256(self, buffer, destaddr): #TZCC_SHA256_Init
|
||||
dataptr = destaddr+0x40
|
||||
ivptr = destaddr+0x20
|
||||
def sbrom_sha256(self, buffer, destaddr): # TZCC_SHA256_Init
|
||||
dataptr = destaddr + 0x40
|
||||
ivptr = destaddr + 0x20
|
||||
outptr = destaddr
|
||||
self.writemem(0x1000108C, 0x18000000)
|
||||
iv = bytes.fromhex("19CDE05BABD9831F8C68059B7F520E513AF54FA572F36E3C85AE67BB67E6096A")
|
||||
self.writemem(ivptr, iv)
|
||||
self.writemem(dataptr,buffer)
|
||||
self.SBROM_CryptoInitDriver(aeskeyptr=0,aesivptr=ivptr,cryptodrivermode=0)
|
||||
self.SBROM_CryptoUpdate(inputptr=dataptr,outputptr=outptr,blockSize=len(buffer), islastblock=1,
|
||||
cryptodrivermode=0,waitforcrypto=3)
|
||||
self.SBROM_CryptoFinishDriver(outptr)
|
||||
self.writemem(dataptr, buffer)
|
||||
self.sbrom_cryptoinitdriver(aesivptr=ivptr, cryptodrivermode=0)
|
||||
self.sbrom_cryptoupdate(inputptr=dataptr, outputptr=outptr, blockSize=len(buffer), islastblock=1,
|
||||
cryptodrivermode=0, waitforcrypto=3)
|
||||
self.sbrom_cryptofinishdriver(outptr)
|
||||
self.writemem(0x10001088, 0x8000000)
|
||||
return 0
|
||||
|
||||
def SBROM_CryptoInitDriver(self, aeskeyptr, aesivptr, cryptodrivermode):
|
||||
if cryptodrivermode&0xFFFFFFFD == 0:
|
||||
#0=v9
|
||||
#1=0x820
|
||||
#2=0
|
||||
#3=0
|
||||
#4=0x1000825
|
||||
#5=v9>>32
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_DIN_TYPE(desc, DmaMode.DMA_DLLI, aesivptr, 0x20, SB_AXI_ID, AXI_SECURE)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_DIN_to_HASH)
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_LOAD_STATE0)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
#0=0
|
||||
#1=0x8000041
|
||||
#2=0
|
||||
#3=0
|
||||
#4=0x4000825
|
||||
#5=0
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_DIN_to_HASH)
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_LOAD_KEY0)
|
||||
desc = HW_DESC_SET_DIN_CONST(desc, 0, 0x10)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
def sbrom_cryptoinitdriver(self, aesivptr, cryptodrivermode):
|
||||
if cryptodrivermode & 0xFFFFFFFD == 0:
|
||||
# 0=v9
|
||||
# 1=0x820
|
||||
# 2=0
|
||||
# 3=0
|
||||
# 4=0x1000825
|
||||
# 5=v9>>32
|
||||
pdesc = hw_desc_init()
|
||||
pdesc = hw_desc_set_din_type(pdesc, DmaMode.DMA_DLLI, aesivptr, 0x20, SB_AXI_ID, AXI_SECURE)
|
||||
pdesc = hw_desc_set_flow_mode(pdesc, FlowMode.S_DIN_to_HASH)
|
||||
pdesc = hw_desc_set_cipher_mode(pdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
pdesc = hw_desc_set_setup_mode(pdesc, SetupOp.SETUP_LOAD_STATE0)
|
||||
self.sasi_sb_adddescsequence(pdesc)
|
||||
# 0=0
|
||||
# 1=0x8000041
|
||||
# 2=0
|
||||
# 3=0
|
||||
# 4=0x4000825
|
||||
# 5=0
|
||||
tdesc = hw_desc_init()
|
||||
tdesc = hw_desc_set_flow_mode(tdesc, FlowMode.S_DIN_to_HASH)
|
||||
tdesc = hw_desc_set_cipher_mode(tdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
tdesc = hw_desc_set_setup_mode(tdesc, SetupOp.SETUP_LOAD_KEY0)
|
||||
tdesc = hw_desc_set_din_const(tdesc, 0, 0x10)
|
||||
self.sasi_sb_adddescsequence(tdesc)
|
||||
|
||||
def SBROM_CryptoUpdate(self, inputptr, outputptr, blockSize, islastblock, cryptodrivermode, waitforcrypto):
|
||||
def sbrom_cryptoupdate(self, inputptr, outputptr, blockSize, islastblock, cryptodrivermode, waitforcrypto):
|
||||
if waitforcrypto != 2 or self.SB_HalWaitDescCompletion(self.dxcc_base) == 0:
|
||||
if islastblock == 1 and (cryptodrivermode & 0xFFFFFFFD) == 0:
|
||||
#0=0
|
||||
#1=0
|
||||
#2=outputptr
|
||||
#3=0x42
|
||||
#4=0x908082B
|
||||
#5=outputptr>>32<<16
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_DOUT_DLLI(desc, outputptr, 0x10, SB_AXI_ID, 0)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_HASH_to_DOUT)
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG1(desc, sep_hash_mode.SEP_HASH_SHA256)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_WRITE_STATE1)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_DIN_TYPE(desc, DmaMode.DMA_DLLI, inputptr, blockSize, SB_AXI_ID, AXI_SECURE)
|
||||
# 0=0
|
||||
# 1=0
|
||||
# 2=outputptr
|
||||
# 3=0x42
|
||||
# 4=0x908082B
|
||||
# 5=outputptr>>32<<16
|
||||
ydesc = hw_desc_init()
|
||||
ydesc = hw_desc_set_dout_dlli(ydesc, outputptr, 0x10, SB_AXI_ID, 0)
|
||||
ydesc = hw_desc_set_flow_mode(ydesc, FlowMode.S_HASH_to_DOUT)
|
||||
ydesc = hw_desc_set_cipher_mode(ydesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
ydesc = hw_desc_set_cipher_config1(ydesc, sep_hash_mode.SEP_HASH_SHA256)
|
||||
ydesc = hw_desc_set_setup_mode(ydesc, SetupOp.SETUP_WRITE_STATE1)
|
||||
self.sasi_sb_adddescsequence(ydesc)
|
||||
udesc = hw_desc_init()
|
||||
udesc = hw_desc_set_din_type(udesc, DmaMode.DMA_DLLI, inputptr, blockSize, SB_AXI_ID, AXI_SECURE)
|
||||
if not cryptodrivermode:
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.DIN_HASH)
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
udesc = hw_desc_set_flow_mode(udesc, FlowMode.DIN_HASH)
|
||||
self.sasi_sb_adddescsequence(udesc)
|
||||
if (waitforcrypto == 2 and not islastblock) or waitforcrypto == 3:
|
||||
self.SB_HalWaitDescCompletion(self.dxcc_base)
|
||||
elif waitforcrypto == 0:
|
||||
|
@ -1326,34 +1329,35 @@ class dxcc(metaclass=LogBase):
|
|||
else:
|
||||
return 0xF2000001
|
||||
|
||||
def SBROM_CryptoFinishDriver(self, outputptr):
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_DOUT_DLLI(desc, outputptr, 0x10, SB_AXI_ID, 0)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_HASH_to_DOUT)
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG0(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG1(desc, sep_hash_mode.SEP_HASH_SHA256)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_WRITE_STATE0)
|
||||
#0 = 0
|
||||
#1 = 0
|
||||
#2 = outputptr
|
||||
#3 = 0x82
|
||||
#4 = 0x80C082B
|
||||
#5 = outputptr>>32<<16
|
||||
self.SaSi_SB_AddDescSequence(desc)
|
||||
def sbrom_cryptofinishdriver(self, outputptr):
|
||||
fdesc = hw_desc_init()
|
||||
fdesc = hw_desc_set_dout_dlli(fdesc, outputptr, 0x10, SB_AXI_ID, 0)
|
||||
fdesc = hw_desc_set_flow_mode(fdesc, FlowMode.S_HASH_to_DOUT)
|
||||
fdesc = hw_desc_set_cipher_mode(fdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
fdesc = hw_desc_set_cipher_config0(fdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
fdesc = hw_desc_set_cipher_config1(fdesc, sep_hash_mode.SEP_HASH_SHA256)
|
||||
fdesc = hw_desc_set_setup_mode(fdesc, SetupOp.SETUP_WRITE_STATE0)
|
||||
# 0 = 0
|
||||
# 1 = 0
|
||||
# 2 = outputptr
|
||||
# 3 = 0x82
|
||||
# 4 = 0x80C082B
|
||||
# 5 = outputptr>>32<<16
|
||||
self.sasi_sb_adddescsequence(fdesc)
|
||||
return self.SB_HalWaitDescCompletion(self.dxcc_base)
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 0=0
|
||||
# 1=0
|
||||
# 2=outputptr
|
||||
# 3=0x42
|
||||
# 4=0x908082B
|
||||
# 5=outputptr>>32<<16
|
||||
desc = HW_DESC_INIT()
|
||||
desc = HW_DESC_SET_DOUT_DLLI(desc, 0, 0x10, SB_AXI_ID, 0)
|
||||
desc = HW_DESC_SET_FLOW_MODE(desc, FlowMode.S_HASH_to_DOUT)
|
||||
desc = HW_DESC_SET_CIPHER_MODE(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = HW_DESC_SET_CIPHER_CONFIG1(desc, sep_hash_mode.SEP_HASH_SHA256)
|
||||
desc = HW_DESC_SET_SETUP_MODE(desc, SetupOp.SETUP_WRITE_STATE1)
|
||||
desc = hw_desc_init()
|
||||
desc = hw_desc_set_dout_dlli(desc, 0, 0x10, SB_AXI_ID, 0)
|
||||
desc = hw_desc_set_flow_mode(desc, FlowMode.S_HASH_to_DOUT)
|
||||
desc = hw_desc_set_cipher_mode(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
|
||||
desc = hw_desc_set_cipher_config1(desc, sep_hash_mode.SEP_HASH_SHA256)
|
||||
desc = hw_desc_set_setup_mode(desc, SetupOp.SETUP_WRITE_STATE1)
|
||||
print(desc)
|
||||
|
|
|
@ -702,13 +702,14 @@ class DALegacy(metaclass=LogBase):
|
|||
if pdram[0] in data or pdram[1] in data:
|
||||
preloader = os.path.join(root, file)
|
||||
print("Detected preloader: " + preloader)
|
||||
self.daconfig.extract_emi(preloader,True)
|
||||
self.daconfig.extract_emi(preloader)
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
break
|
||||
if self.usbread(4) == pack(">I", 0xBC4): # Nand_Status
|
||||
nand_id_count = unpack(">H", self.usbread(2))[0]
|
||||
self.info("Reading nand info ...")
|
||||
nand_ids = []
|
||||
for i in range(0, nand_id_count):
|
||||
nand_ids.append(unpack(">H", self.usbread(2))[0])
|
||||
|
@ -724,6 +725,7 @@ class DALegacy(metaclass=LogBase):
|
|||
val = 0x14
|
||||
self.usbwrite(pack(">I", val))
|
||||
if self.usbread(1) == self.Rsp.ACK:
|
||||
self.info("Sending dram info ...")
|
||||
dramlength = len(self.daconfig.emi)
|
||||
if val in [0x10, 0x14, 0x15]:
|
||||
dramlength = unpack(">I", self.usbread(0x4))[0] # 0x000000BC
|
||||
|
@ -745,7 +747,7 @@ class DALegacy(metaclass=LogBase):
|
|||
self.debug(f"M_EXT_RAM_RET : {m_ext_ram_ret}")
|
||||
if m_ext_ram_ret != 0:
|
||||
self.error("Preloader error: %d => %s" % (m_ext_ram_ret, error_to_string(m_ext_ram_ret)))
|
||||
self.mtk.port.close()
|
||||
self.mtk.port.close(reset=False)
|
||||
sys.exit(0)
|
||||
m_ext_ram_type = self.usbread(1)[0] # 0x02 HW_RAM_DRAM
|
||||
self.debug(f"M_EXT_RAM_TYPE : {m_ext_ram_type}")
|
||||
|
@ -755,7 +757,7 @@ class DALegacy(metaclass=LogBase):
|
|||
self.debug(f"M_EXT_RAM_SIZE : {m_ext_ram_size}")
|
||||
else:
|
||||
self.error("Preloader needed due to dram config.")
|
||||
self.mtk.port.close()
|
||||
self.mtk.port.close(reset=True)
|
||||
sys.exit(0)
|
||||
return buffer
|
||||
|
||||
|
@ -857,14 +859,13 @@ class DALegacy(metaclass=LogBase):
|
|||
self.daconfig.flashsize = self.sdc["m_sdmmc_ua_size"]
|
||||
elif self.daconfig.flashtype == "nor":
|
||||
self.daconfig.flashsize = self.nor["m_nor_flash_size"]
|
||||
if os.name != "nt":
|
||||
self.info("Reconnecting to preloader")
|
||||
self.set_usb_cmd()
|
||||
self.mtk.port.close()
|
||||
time.sleep(2)
|
||||
while not self.mtk.port.cdc.connect():
|
||||
time.sleep(0.5)
|
||||
self.info("Connected to preloader")
|
||||
self.info("Reconnecting to preloader")
|
||||
self.set_usb_cmd()
|
||||
self.mtk.port.close(reset=False)
|
||||
time.sleep(2)
|
||||
while not self.mtk.port.cdc.connect():
|
||||
time.sleep(0.5)
|
||||
self.info("Connected to preloader")
|
||||
self.check_usb_cmd()
|
||||
return True
|
||||
return False
|
||||
|
@ -904,7 +905,7 @@ class DALegacy(metaclass=LogBase):
|
|||
|
||||
def close(self):
|
||||
self.finish(0x0) # DISCONNECT_USB_AND_RELEASE_POWERKEY
|
||||
self.mtk.port.close()
|
||||
self.mtk.port.close(reset=True)
|
||||
|
||||
def brom_send(self, dasetup, da, stage, packetsize=0x1000):
|
||||
offset = dasetup.da[stage]["m_buf"]
|
||||
|
@ -972,7 +973,7 @@ class DALegacy(metaclass=LogBase):
|
|||
return True
|
||||
return False
|
||||
|
||||
def sdmmc_write_data(self, addr, length, filename, offset=0, parttype=None, display=True):
|
||||
def sdmmc_write_data(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
if parttype is None or parttype == "user":
|
||||
length = min(length, self.emmc["m_emmc_ua_size"])
|
||||
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
|
||||
|
@ -1008,34 +1009,39 @@ class DALegacy(metaclass=LogBase):
|
|||
else:
|
||||
storage = DaStorage.MTK_DA_STORAGE_EMMC
|
||||
|
||||
if filename != "":
|
||||
with open(filename, "rb") as rf:
|
||||
rf.seek(offset)
|
||||
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))
|
||||
self.usbwrite(pack(">Q", addr))
|
||||
self.usbwrite(pack(">Q", length))
|
||||
self.usbwrite(pack(">I", 0x100000))
|
||||
if self.usbread(1) != self.Rsp.ACK:
|
||||
self.error("Couldn't send sdmmc_write_data header")
|
||||
return False
|
||||
offset = 0
|
||||
while offset < length:
|
||||
self.usbwrite(self.Rsp.ACK)
|
||||
count = min(0x100000, length - offset)
|
||||
data = bytearray(rf.read(count))
|
||||
self.usbwrite(data)
|
||||
chksum = sum(data) & 0xFFFF
|
||||
self.usbwrite(pack(">H", chksum))
|
||||
if self.usbread(1) != self.Rsp.CONT_CHAR:
|
||||
self.error("Data ack failed for sdmmc_write_data")
|
||||
return False
|
||||
self.progress.show_progress("Write",offset,length,display)
|
||||
offset += count
|
||||
self.progress.show_progress("Write", 100, 100, display)
|
||||
return True
|
||||
if filename is not None:
|
||||
fh=open(filename, "rb")
|
||||
fh.seek(offset)
|
||||
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))
|
||||
self.usbwrite(pack(">Q", addr))
|
||||
self.usbwrite(pack(">Q", length))
|
||||
self.usbwrite(pack(">I", 0x100000))
|
||||
if self.usbread(1) != self.Rsp.ACK:
|
||||
self.error("Couldn't send sdmmc_write_data header")
|
||||
return False
|
||||
offset = 0
|
||||
while offset < length:
|
||||
self.usbwrite(self.Rsp.ACK)
|
||||
count = min(0x100000, length - offset)
|
||||
if fh:
|
||||
data = bytearray(fh.read(count))
|
||||
else:
|
||||
data = wdata[offset:offset+count]
|
||||
self.usbwrite(data)
|
||||
chksum = sum(data) & 0xFFFF
|
||||
self.usbwrite(pack(">H", chksum))
|
||||
if self.usbread(1) != self.Rsp.CONT_CHAR:
|
||||
self.error("Data ack failed for sdmmc_write_data")
|
||||
return False
|
||||
self.progress.show_progress("Write",offset,length,display)
|
||||
offset += count
|
||||
if fh:
|
||||
fh.close()
|
||||
self.progress.show_progress("Write", 100, 100, display)
|
||||
return True
|
||||
|
||||
def sdmmc_write_image(self, addr, length, filename, display=True):
|
||||
if filename != "":
|
||||
|
@ -1080,9 +1086,9 @@ class DALegacy(metaclass=LogBase):
|
|||
return True
|
||||
return True
|
||||
|
||||
def writeflash(self, addr, length, filename, partitionname, offset=0, parttype=None, display=True):
|
||||
def writeflash(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
return self.sdmmc_write_data(addr=addr, length=length, filename=filename, offset=offset, parttype=parttype,
|
||||
display=display)
|
||||
wdata=wdata, display=display)
|
||||
|
||||
def formatflash(self, addr, length, parttype=None, display=True):
|
||||
if parttype is None or parttype == "user" or parttype == "":
|
||||
|
@ -1212,7 +1218,7 @@ class DALegacy(metaclass=LogBase):
|
|||
size = bytestoread
|
||||
if bytestoread > packetsize:
|
||||
size = packetsize
|
||||
wf.write(self.usbread(size,0x400))
|
||||
wf.write(self.usbread(size))
|
||||
bytestoread -= size
|
||||
checksum = unpack(">H", self.usbread(1)+self.usbread(1))[0]
|
||||
self.debug("Checksum: %04X" % checksum)
|
||||
|
@ -1227,7 +1233,7 @@ class DALegacy(metaclass=LogBase):
|
|||
size = bytestoread
|
||||
if bytestoread > packetsize:
|
||||
size = packetsize
|
||||
buffer.extend(self.usbread(size,0x400))
|
||||
buffer.extend(self.usbread(size))
|
||||
bytestoread -= size
|
||||
checksum = unpack(">H", self.usbread(2))[0]
|
||||
self.debug("Checksum: %04X" % checksum)
|
||||
|
|
|
@ -9,12 +9,14 @@ from mtkclient.Library.error import ErrorHandler
|
|||
from mtkclient.Library.daconfig import DAconfig
|
||||
from mtkclient.Library.mtk_dalegacy import DALegacy
|
||||
from mtkclient.Library.mtk_daxflash import DAXFlash
|
||||
|
||||
from mtkclient.config.brom_config import damodes
|
||||
from mtkclient.Library.xflash_ext import xflashext
|
||||
|
||||
class DAloader(metaclass=LogBase):
|
||||
def __init__(self, mtk, loglevel=logging.INFO):
|
||||
self.__logger = logsetup(self, self.__logger, loglevel)
|
||||
self.mtk = mtk
|
||||
self.config = mtk.config
|
||||
self.loglevel = loglevel
|
||||
self.eh = ErrorHandler()
|
||||
self.config = self.mtk.config
|
||||
|
@ -26,14 +28,16 @@ class DAloader(metaclass=LogBase):
|
|||
self.rword = self.mtk.port.rword
|
||||
self.daconfig = DAconfig(mtk=self.mtk, loader=self.mtk.config.loader,
|
||||
preloader=self.mtk.config.preloader, loglevel=loglevel)
|
||||
self.xft = None
|
||||
self.da = None
|
||||
|
||||
def writestate(self):
|
||||
config = {}
|
||||
config["xflash"] = self.xflash
|
||||
config["xflash"] = self.mtk.config.chipconfig.damode==damodes.XFLASH
|
||||
config["hwcode"] = self.config.hwcode
|
||||
config["flashtype"] = self.daconfig.flashtype
|
||||
config["flashsize"] = self.daconfig.flashsize
|
||||
if not self.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"]
|
||||
|
@ -47,12 +51,15 @@ class DAloader(metaclass=LogBase):
|
|||
def reinit(self):
|
||||
if os.path.exists(".state"):
|
||||
config = json.loads(open(".state", "r").read())
|
||||
xflash = config["xflash"]
|
||||
if xflash:
|
||||
self.config.hwcode = config["hwcode"]
|
||||
self.xflash = config["xflash"]
|
||||
self.config.init_hwcode(self.config.hwcode)
|
||||
if self.xflash:
|
||||
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
|
||||
self.daconfig.flashtype = config["flashtype"]
|
||||
self.daconfig.flashsize = config["flashsize"]
|
||||
self.da.reinit()
|
||||
self.xft=xflashext(self.mtk, self.da, self.loglevel)
|
||||
else:
|
||||
self.da = DALegacy(self.mtk, self.daconfig, self.loglevel)
|
||||
self.daconfig.flashtype = config["flashtype"]
|
||||
|
@ -69,6 +76,7 @@ class DAloader(metaclass=LogBase):
|
|||
self.da.nand["m_nand_flash_size"] = config["m_nand_flash_size"]
|
||||
self.da.sdc["m_sdmmc_ua_size"] = config["m_sdmmc_ua_size"]
|
||||
self.da.nor["m_nor_flash_size"] = config["m_nor_flash_size"]
|
||||
self.xft = None
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -83,6 +91,7 @@ class DAloader(metaclass=LogBase):
|
|||
self.xflash = True
|
||||
if self.xflash:
|
||||
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
|
||||
self.xft = xflashext(self.mtk, self.da, self.loglevel)
|
||||
else:
|
||||
self.da = DALegacy(self.mtk, self.daconfig, self.loglevel)
|
||||
|
||||
|
@ -127,16 +136,52 @@ class DAloader(metaclass=LogBase):
|
|||
|
||||
def upload_da(self, preloader=None):
|
||||
self.daconfig.setup()
|
||||
self.daconfig.extract_emi(preloader, legacy=self.mtk.config.chipconfig.damode == 0)
|
||||
self.daconfig.extract_emi(preloader)
|
||||
self.set_da()
|
||||
return self.da.upload_da()
|
||||
|
||||
def writeflash(self, addr, length, filename, partitionname, offset=0, parttype=None, display=True):
|
||||
def writeflash(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
return self.da.writeflash(addr=addr, length=length, filename=filename, offset=offset,
|
||||
partitionname=partitionname, parttype=parttype, display=display)
|
||||
parttype=parttype, wdata=wdata, display=display)
|
||||
|
||||
def formatflash(self, addr, length, partitionname, parttype, display=True):
|
||||
return self.da.formatflash(addr=addr, length=length, parttype=parttype)
|
||||
|
||||
def readflash(self, addr, length, filename, parttype, display=True):
|
||||
return self.da.readflash(addr=addr, length=length, filename=filename, parttype=parttype, display=display)
|
||||
|
||||
def peek(self, addr: int, length:int):
|
||||
if self.xflash:
|
||||
return self.xft.custom_read(addr=addr, length=length)
|
||||
self.error("Device is not in xflash mode, cannot run peek cmd.")
|
||||
return b""
|
||||
|
||||
def poke(self, addr: int, data: bytes or bytearray):
|
||||
if self.xflash:
|
||||
return self.xft.custom_write(addr=addr, data=data)
|
||||
self.error("Device is not in xflash mode, cannot run poke cmd.")
|
||||
return False
|
||||
|
||||
def keys(self):
|
||||
if self.xflash:
|
||||
return self.xft.generate_keys()
|
||||
self.error("Device is not in xflash mode, cannot run keys cmd.")
|
||||
return False
|
||||
|
||||
def seccfg(self, lockflag):
|
||||
if self.xflash:
|
||||
return self.xft.seccfg(lockflag)
|
||||
self.error("Device is not in xflash mode, cannot run unlock cmd.")
|
||||
return False
|
||||
|
||||
def read_rpmb(self, filename=None):
|
||||
if self.xflash:
|
||||
return self.xft.read_rpmb(filename)
|
||||
self.error("Device is not in xflash mode, cannot run read rpmb cmd.")
|
||||
return False
|
||||
|
||||
def write_rpmb(self, filename=None):
|
||||
if self.xflash:
|
||||
return self.xft.write_rpmb(filename)
|
||||
self.error("Device is not in xflash mode, cannot run write rpmb cmd.")
|
||||
return False
|
File diff suppressed because it is too large
Load diff
|
@ -124,6 +124,8 @@ class Preloader(metaclass=LogBase):
|
|||
self.sendcmd = self.mtk.port.mtk_cmd
|
||||
|
||||
def init(self, maxtries=None, display=True):
|
||||
if os.path.exists(".state"):
|
||||
os.remove(".state")
|
||||
readsocid=self.config.readsocid
|
||||
skipwdt = self.config.skipwdt
|
||||
|
||||
|
@ -166,6 +168,15 @@ class Preloader(metaclass=LogBase):
|
|||
self.info("\tCQ_DMA addr:\t\t" + hex(self.config.chipconfig.cqdma_base))
|
||||
self.info("\tVar1:\t\t\t" + hex(self.config.chipconfig.var1))
|
||||
|
||||
if not skipwdt:
|
||||
if self.display:
|
||||
self.info("Disabling Watchdog...")
|
||||
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.txt"), "w") as wf:
|
||||
wf.write(hex(self.config.hwcode))
|
||||
self.config.target_config = self.get_target_config(self.display)
|
||||
res = self.get_hw_sw_ver()
|
||||
self.config.hwsubcode = 0
|
||||
self.config.hwver = 0
|
||||
|
@ -178,17 +189,6 @@ class Preloader(metaclass=LogBase):
|
|||
self.info("\tHW subcode:\t\t" + hex(self.config.hwsubcode))
|
||||
self.info("\tHW Ver:\t\t\t" + hex(self.config.hwver))
|
||||
self.info("\tSW Ver:\t\t\t" + hex(self.config.swver))
|
||||
|
||||
if not skipwdt:
|
||||
if self.display:
|
||||
self.info("Disabling Watchdog...")
|
||||
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.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.txt"), "wb") as wf:
|
||||
|
|
|
@ -16,13 +16,13 @@ class Partition(metaclass=LogBase):
|
|||
|
||||
def get_gpt(self, gpt_num_part_entries, gpt_part_entry_size, gpt_part_entry_start_lba, 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:
|
||||
if data[:9] == b"EMMC_BOOT" and self.read_pmt is not None:
|
||||
partdata, partentries = self.read_pmt()
|
||||
if partdata == b"":
|
||||
return None, None
|
||||
else:
|
||||
return partdata, partentries
|
||||
elif data[:8] == b"UFS_BOOT" and self.read_pmt:
|
||||
elif data[:8] == b"UFS_BOOT" and self.read_pmt is not None:
|
||||
partdata, partentries = self.read_pmt()
|
||||
if partdata == b"":
|
||||
return None, None
|
||||
|
|
|
@ -182,7 +182,7 @@ class PLTools(metaclass=LogBase):
|
|||
|
||||
def crasher(self, mtk, enforcecrash):
|
||||
plt = PLTools(mtk, self.__logger.level)
|
||||
if enforcecrash or not (mtk.port.cdc.vid == 0xE8D and mtk.port.cdc.pid == 0x0003):
|
||||
if enforcecrash or self.config.meid is None:
|
||||
self.info("We're not in bootrom, trying to crash da...")
|
||||
for crashmode in range(0, 3):
|
||||
try:
|
||||
|
|
138
mtkclient/Library/usblib.py
Normal file → Executable file
138
mtkclient/Library/usblib.py
Normal file → Executable file
|
@ -9,7 +9,6 @@ import usb.util
|
|||
import time
|
||||
import inspect
|
||||
import traceback
|
||||
import array
|
||||
import usb.backend.libusb0
|
||||
import usb.backend.libusb1
|
||||
from struct import calcsize
|
||||
|
@ -73,7 +72,7 @@ class usb_class(metaclass=LogBase):
|
|||
def __init__(self, loglevel=logging.INFO, portconfig=None, devclass=-1):
|
||||
self.load_windows_dll()
|
||||
self.connected = False
|
||||
self.timeout = None
|
||||
self.timeout = 1000
|
||||
self.vid = None
|
||||
self.pid = None
|
||||
self.stopbits = None
|
||||
|
@ -94,7 +93,6 @@ class usb_class(metaclass=LogBase):
|
|||
self.warning = self.__logger.warning
|
||||
self.debug = self.__logger.debug
|
||||
self.__logger.setLevel(loglevel)
|
||||
self.buffer = array.array('B', [0]) * 1048576
|
||||
if loglevel == logging.DEBUG:
|
||||
logfilename = os.path.join("logs", "log.txt")
|
||||
fh = logging.FileHandler(logfilename)
|
||||
|
@ -103,7 +101,7 @@ class usb_class(metaclass=LogBase):
|
|||
if sys.platform.startswith('freebsd') or sys.platform.startswith('linux'):
|
||||
self.backend = usb.backend.libusb1.get_backend(find_library=lambda x: "libusb-1.0.so")
|
||||
elif sys.platform.startswith('win32'):
|
||||
if calcsize("P")*8==64:
|
||||
if calcsize("P") * 8 == 64:
|
||||
self.backend = usb.backend.libusb1.get_backend(find_library=lambda x: "libusb-1.0.dll")
|
||||
else:
|
||||
self.backend = usb.backend.libusb1.get_backend(find_library=lambda x: "libusb32-1.0.dll")
|
||||
|
@ -284,6 +282,9 @@ class usb_class(metaclass=LogBase):
|
|||
if e.errno == 13:
|
||||
self.backend = usb.backend.libusb0.get_backend()
|
||||
self.device = usb.core.find(idVendor=self.vid, idProduct=self.pid, backend=self.backend)
|
||||
if self.configuration is None:
|
||||
self.error("Couldn't get device configuration.")
|
||||
return False
|
||||
if self.interface == -1:
|
||||
for interfacenum in range(0, self.configuration.bNumInterfaces):
|
||||
itf = usb.util.find_descriptor(self.configuration, bInterfaceNumber=interfacenum)
|
||||
|
@ -303,9 +304,9 @@ class usb_class(metaclass=LogBase):
|
|||
if self.interface != -1:
|
||||
itf = usb.util.find_descriptor(self.configuration, bInterfaceNumber=self.interface)
|
||||
try:
|
||||
if self.device.is_kernel_driver_active(self.interface):
|
||||
if self.device.is_kernel_driver_active(0):
|
||||
self.debug("Detaching kernel driver")
|
||||
self.device.detach_kernel_driver(self.interface)
|
||||
self.device.detach_kernel_driver(0)
|
||||
except Exception as err:
|
||||
self.debug("No kernel driver supported: " + str(err))
|
||||
try:
|
||||
|
@ -314,7 +315,13 @@ class usb_class(metaclass=LogBase):
|
|||
pass
|
||||
|
||||
try:
|
||||
if self.interface!=0:
|
||||
if self.device.is_kernel_driver_active(self.interface):
|
||||
self.debug("Detaching kernel driver")
|
||||
self.device.detach_kernel_driver(self.interface)
|
||||
except Exception as err:
|
||||
self.debug("No kernel driver supported: " + str(err))
|
||||
try:
|
||||
if self.interface != 0:
|
||||
usb.util.claim_interface(self.device, self.interface)
|
||||
except:
|
||||
pass
|
||||
|
@ -346,12 +353,11 @@ class usb_class(metaclass=LogBase):
|
|||
def close(self, reset=False):
|
||||
if self.connected:
|
||||
try:
|
||||
# self.device.reset()
|
||||
if reset:
|
||||
self.device.reset()
|
||||
if not self.device.is_kernel_driver_active(self.interface):
|
||||
# self.device.attach_kernel_driver(self.interface) #Do NOT uncomment
|
||||
self.device.attach_kernel_driver(0)
|
||||
if reset:
|
||||
self.device.reset()
|
||||
except Exception as err:
|
||||
self.debug(str(err))
|
||||
pass
|
||||
|
@ -371,7 +377,7 @@ class usb_class(metaclass=LogBase):
|
|||
except usb.core.USBError as err:
|
||||
error = str(err.strerror)
|
||||
if "timeout" in error:
|
||||
time.sleep(0.01)
|
||||
# time.sleep(0.01)
|
||||
try:
|
||||
self.EP_OUT.write(b'')
|
||||
except Exception as err:
|
||||
|
@ -382,12 +388,14 @@ class usb_class(metaclass=LogBase):
|
|||
i = 0
|
||||
while pos < len(command):
|
||||
try:
|
||||
self.EP_OUT.write(command[pos:pos + pktsize])
|
||||
ctr = self.EP_OUT.write(command[pos:pos + pktsize])
|
||||
if ctr <= 0:
|
||||
self.info(ctr)
|
||||
pos += pktsize
|
||||
except Exception as err:
|
||||
self.debug(str(err))
|
||||
# print("Error while writing")
|
||||
time.sleep(0.01)
|
||||
# time.sleep(0.01)
|
||||
i += 1
|
||||
if i == 3:
|
||||
return False
|
||||
|
@ -395,43 +403,38 @@ class usb_class(metaclass=LogBase):
|
|||
self.verify_data(bytearray(command), "TX:")
|
||||
return True
|
||||
|
||||
def read(self, maxlength=None, timeout=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))
|
||||
rxBuffer = array.array('B')
|
||||
extend = rxBuffer.extend
|
||||
if timeout is None:
|
||||
timeout = self.timeout
|
||||
buffer = self.buffer[:maxlength]
|
||||
ep_read = self.EP_IN.read
|
||||
while len(rxBuffer) == 0:
|
||||
def usbread(self, resplen):
|
||||
if resplen <= 0:
|
||||
self.info("Warning !")
|
||||
res = bytearray()
|
||||
timeout = 0
|
||||
loglevel = self.loglevel
|
||||
epr = self.EP_IN.read
|
||||
wMaxPacketSize = self.EP_IN.wMaxPacketSize
|
||||
extend = res.extend
|
||||
while len(res) < resplen:
|
||||
try:
|
||||
length = ep_read(buffer, timeout)
|
||||
extend(buffer[:length])
|
||||
if len(rxBuffer) > 0:
|
||||
if self.loglevel == logging.DEBUG:
|
||||
self.verify_data(rxBuffer, "RX:")
|
||||
return bytearray(rxBuffer)
|
||||
extend(epr(resplen))
|
||||
except usb.core.USBError as e:
|
||||
error = str(e.strerror)
|
||||
if "timed out" in error:
|
||||
# if platform.system()=='Windows':
|
||||
# time.sleep(0.05)
|
||||
# print("Waiting...")
|
||||
self.debug("Timed out")
|
||||
self.debug(rxBuffer)
|
||||
return bytearray(rxBuffer)
|
||||
if timeout == 4:
|
||||
return b""
|
||||
timeout += 1
|
||||
pass
|
||||
elif "Overflow" in error:
|
||||
self.error("USB Overflow")
|
||||
sys.exit(0)
|
||||
elif e.errno is not None:
|
||||
print(repr(e), type(e), e.errno)
|
||||
sys.exit(0)
|
||||
return b""
|
||||
else:
|
||||
break
|
||||
return bytearray(rxBuffer)
|
||||
self.info(repr(e), type(e), e.errno)
|
||||
return b""
|
||||
|
||||
if loglevel == logging.DEBUG:
|
||||
self.debug(inspect.currentframe().f_back.f_code.co_name + ":" + hex(resplen))
|
||||
if self.loglevel == logging.DEBUG:
|
||||
self.verify_data(res[:resplen], "RX:")
|
||||
return res[:resplen]
|
||||
|
||||
def ctrl_transfer(self, bmRequestType, bRequest, wValue, wIndex, data_or_wLength):
|
||||
ret = self.device.ctrl_transfer(bmRequestType=bmRequestType, bRequest=bRequest, wValue=wValue, wIndex=wIndex,
|
||||
|
@ -454,9 +457,9 @@ class usb_class(metaclass=LogBase):
|
|||
def usbwrite(self, data, pktsize=None):
|
||||
if pktsize is None:
|
||||
pktsize = len(data)
|
||||
size = self.write(data, pktsize)
|
||||
res = self.write(data, pktsize)
|
||||
# port->flush()
|
||||
return size
|
||||
return res
|
||||
|
||||
def usbreadwrite(self, data, resplen):
|
||||
self.usbwrite(data) # size
|
||||
|
@ -487,25 +490,6 @@ class usb_class(metaclass=LogBase):
|
|||
def rbyte(self, count=1):
|
||||
return self.usbread(count)
|
||||
|
||||
def usbread(self, resplen, size=None):
|
||||
if size is None:
|
||||
size = resplen
|
||||
res = bytearray()
|
||||
timeout = 0
|
||||
while len(res) < resplen:
|
||||
v=self.read(size)
|
||||
res.extend(v)
|
||||
if len(res) == resplen:
|
||||
break
|
||||
if len(res) == 0:
|
||||
time.sleep(0.001)
|
||||
if timeout == 4:
|
||||
return res
|
||||
timeout += 1
|
||||
elif len(v)==0:
|
||||
break
|
||||
return res
|
||||
|
||||
|
||||
class scsi_cmds(Enum):
|
||||
SC_TEST_UNIT_READY = 0x00,
|
||||
|
@ -671,8 +655,9 @@ class scsi:
|
|||
print("Sent HTC ums adb enable command: %x" % ret)
|
||||
|
||||
def send_zte_adbenable(self): # zte blade
|
||||
common_cmnd = b"\x86zte\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # reserve_cmd + 'zte' + len + flag
|
||||
common_cmnd2 = b"\x86zte\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # reserve_cmd + 'zte' + len + flag
|
||||
# reserve_cmd + 'zte' + len + flag
|
||||
cmnds = [b"\x86zte\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||
b"\x86zte\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]
|
||||
'''
|
||||
Flag values:
|
||||
0: disable adbd ---for 736T
|
||||
|
@ -681,23 +666,24 @@ class scsi:
|
|||
3: enable adbd ---for All except 736T
|
||||
'''
|
||||
lun = 0
|
||||
datasize = common_cmnd[4]
|
||||
timeout = 5000
|
||||
ret_tag = self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, datasize)
|
||||
ret_tag += self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, datasize)
|
||||
ret_tag = self.send_mass_storage_command(lun, common_cmnd2, USB_DIR_IN, datasize)
|
||||
ret_tag += self.send_mass_storage_command(lun, common_cmnd2, USB_DIR_IN, datasize)
|
||||
for cmnd in cmnds:
|
||||
datasize = cmnd[4]
|
||||
ret_tag = self.send_mass_storage_command(lun, cmnd, USB_DIR_IN, datasize)
|
||||
ret_tag += self.send_mass_storage_command(lun, cmnd, USB_DIR_IN, datasize)
|
||||
if datasize > 0:
|
||||
data = self.usb.read(datasize, timeout)
|
||||
print("DATA: " + hexlify(data).decode('utf-8'))
|
||||
print("Send HTC adb enable command")
|
||||
|
||||
def send_fih_adbenable(self): # motorola xt560, nokia 3.1, #f_mass_storage.c
|
||||
def send_fih_adbenable(self):
|
||||
# motorola xt560, nokia 3.1, #f_mass_storage.c
|
||||
if self.usb.connect():
|
||||
print("Sending FIH adb enable command")
|
||||
datasize = 0x24
|
||||
common_cmnd = bytes([self.SC_SWITCH_PORT]) + b"FI1" + struct.pack("<H",
|
||||
datasize) # reserve_cmd + 'FI' + flag + len + none
|
||||
datasize)
|
||||
# reserve_cmd + 'FI' + flag + len + none
|
||||
'''
|
||||
Flag values:
|
||||
common_cmnd[3]->1: Enable adb daemon from mass_storage
|
||||
|
@ -728,13 +714,15 @@ class scsi:
|
|||
print("Sent alcatel adb enable command")
|
||||
self.usb.close()
|
||||
|
||||
def send_fih_root(
|
||||
self): # motorola xt560, nokia 3.1, huawei u8850, huawei Ideos X6, lenovo s2109, triumph M410, viewpad 7, #f_mass_storage.c
|
||||
def send_fih_root(self):
|
||||
# motorola xt560, nokia 3.1, huawei u8850, huawei Ideos X6,
|
||||
# lenovo s2109, triumph M410, viewpad 7, #f_mass_storage.c
|
||||
if self.usb.connect():
|
||||
print("Sending FIH root command")
|
||||
datasize = 0x24
|
||||
common_cmnd = bytes([self.SC_SWITCH_ROOT]) + b"FIH" + struct.pack("<H",
|
||||
datasize) # reserve_cmd + 'FIH' + len + flag + none
|
||||
datasize)
|
||||
# reserve_cmd + 'FIH' + len + flag + none
|
||||
lun = 0
|
||||
# datasize = common_cmnd[4]
|
||||
timeout = 5000
|
||||
|
|
|
@ -13,6 +13,7 @@ import colorama
|
|||
import copy
|
||||
import time
|
||||
import io
|
||||
import datetime as dt
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding = 'utf-8')
|
||||
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding = 'utf-8')
|
||||
|
||||
|
@ -28,27 +29,71 @@ except ImportError:
|
|||
from struct import unpack, pack
|
||||
|
||||
|
||||
def find_binary(data, strf, pos=0):
|
||||
t = strf.split(b".")
|
||||
pre = 0
|
||||
offsets = []
|
||||
while pre != -1:
|
||||
pre = data[pos:].find(t[0], pre)
|
||||
if pre == -1:
|
||||
if len(offsets) > 0:
|
||||
for offset in offsets:
|
||||
error = 0
|
||||
rt = offset + len(t[0])
|
||||
for i in range(1, len(t)):
|
||||
if t[i] == b'':
|
||||
rt += 1
|
||||
continue
|
||||
rt += 1
|
||||
prep = data[rt:].find(t[i])
|
||||
if prep != 0:
|
||||
error = 1
|
||||
break
|
||||
rt += len(t[i])
|
||||
if error == 0:
|
||||
return offset
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
offsets.append(pre)
|
||||
pre += 1
|
||||
return None
|
||||
|
||||
class progress:
|
||||
def __init__(self, pagesize):
|
||||
self.progtime = 0
|
||||
self.prog = 0
|
||||
self.progpos = 0
|
||||
self.start = time.time()
|
||||
self.pagesize = pagesize
|
||||
|
||||
def calcProcessTime(self, starttime, cur_iter, max_iter):
|
||||
telapsed = time.time() - starttime
|
||||
if telapsed > 0 and cur_iter > 0:
|
||||
testimated = (telapsed / cur_iter) * (max_iter)
|
||||
finishtime = starttime + testimated
|
||||
finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time
|
||||
lefttime = testimated - telapsed # in seconds
|
||||
return (int(telapsed), int(lefttime), finishtime)
|
||||
else:
|
||||
return 0,0,""
|
||||
|
||||
def show_progress(self, prefix, pos, total, display=True):
|
||||
t0 = time.time()
|
||||
prog = round(float(pos) / float(total) * float(100), 2)
|
||||
prog = round(float(pos) / float(total) * float(100), 1)
|
||||
if prog == 0:
|
||||
self.prog = 0
|
||||
self.start = time.time()
|
||||
self.progtime = time.time()
|
||||
self.progpos = pos
|
||||
print_progress(prog, 100, prefix='Progress:',
|
||||
suffix=prefix + ' (Sector %d of %d) %0.2f MB/s' %
|
||||
print_progress(prog, 100, prefix='Done',
|
||||
suffix=prefix + ' (Sector 0x%X of 0x%X) %0.2f MB/s' %
|
||||
(pos // self.pagesize,
|
||||
total // self.pagesize,
|
||||
0), bar_length=50)
|
||||
|
||||
if prog > self.prog:
|
||||
if display:
|
||||
t0 = time.time()
|
||||
tdiff = t0 - self.progtime
|
||||
datasize = (pos - self.progpos) / 1024 / 1024
|
||||
if datasize != 0 and tdiff != 0:
|
||||
|
@ -58,8 +103,24 @@ class progress:
|
|||
throughput = 0
|
||||
else:
|
||||
throughput = 0
|
||||
telapsed, lefttime, finishtime = self.calcProcessTime(self.start, prog, 100)
|
||||
hinfo = ""
|
||||
if lefttime > 0:
|
||||
sec = lefttime
|
||||
if sec > 60:
|
||||
min = sec // 60
|
||||
sec = sec % 60
|
||||
if min > 60:
|
||||
h = min // 24
|
||||
min = min % 24
|
||||
hinfo = "%02dh:%02dm:%02ds left" % (h, min, sec)
|
||||
else:
|
||||
hinfo = "%02dm:%02ds left" % (min, sec)
|
||||
else:
|
||||
hinfo = "%02ds left" % sec
|
||||
|
||||
print_progress(prog, 100, prefix='Progress:',
|
||||
suffix=prefix + ' (Sector %d of %d) %0.2f MB/s' %
|
||||
suffix=prefix + f' (Sector 0x%X of 0x%X, {hinfo}) %0.2f MB/s' %
|
||||
(pos // self.pagesize,
|
||||
total // self.pagesize,
|
||||
throughput), bar_length=50)
|
||||
|
|
510
mtkclient/Library/xflash_ext.py
Normal file
510
mtkclient/Library/xflash_ext.py
Normal file
|
@ -0,0 +1,510 @@
|
|||
import os
|
||||
from struct import unpack, pack
|
||||
from mtkclient.config.payloads import pathconfig
|
||||
from mtkclient.Library.error import ErrorHandler
|
||||
from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto
|
||||
from mtkclient.Library.utils import LogBase, progress, logsetup, find_binary
|
||||
from binascii import hexlify
|
||||
import hashlib
|
||||
|
||||
|
||||
class XCmd:
|
||||
CUSTOM_ACK = 0x0F0000
|
||||
CUSTOM_READ = 0x0F0001
|
||||
CUSTOM_WRITE = 0x0F0002
|
||||
CUSTOM_WRITEREGISTER = 0x0F0003
|
||||
CUSTOM_INIT_RPMB = 0x0F0004
|
||||
CUSTOM_READ_RPMB = 0x0F0005
|
||||
CUSTOM_WRITE_RPMB = 0x0F0006
|
||||
CUSTOM_INIT_UFS_RPMB = 0x0F0007
|
||||
CUSTOM_READ_UFS_RPMB = 0x0F0008
|
||||
CUSTOM_WRITE_UFS_RPMB = 0x0F0009
|
||||
|
||||
class seccfg:
|
||||
def __init__(self, hwc):
|
||||
self.hwc = hwc
|
||||
self.magic = 0x4D4D4D4D
|
||||
self.seccfg_ver = None
|
||||
self.seccfg_size = None
|
||||
self.lock_state = None
|
||||
self.critical_lock_state = None
|
||||
self.sboot_runtime = None
|
||||
self.endflag = 0x45454545
|
||||
self.hash = b""
|
||||
|
||||
def parse(self, data):
|
||||
seccfg_data = unpack("<IIIIIII", data[:7 * 4])
|
||||
self.magic, self.seccfg_ver, self.seccfg_size, self.lock_state, self.critical_lock_state, \
|
||||
self.sboot_runtime, self.endflag = seccfg_data
|
||||
self.hash = data[7 * 4:(7 * 4) + 32]
|
||||
if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
|
||||
self.error("Unknown seccfg structure !")
|
||||
return False
|
||||
return True
|
||||
|
||||
"""
|
||||
LKS_DEFAULT = 0x01
|
||||
LKS_MP_DEFAULT = 0x02
|
||||
LKS_UNLOCK = 0x03
|
||||
LKS_LOCK = 0x04
|
||||
LKS_VERIFIED = 0x05
|
||||
LKS_CUSTOM = 0x06
|
||||
LKCS_UNLOCK = 0x01
|
||||
LKCS_LOCK = 0x02
|
||||
SBOOT_RUNTIME_OFF = 0
|
||||
SBOOT_RUNTIME_ON = 1
|
||||
"""
|
||||
|
||||
def create(self, lockflag: str, locktype: str):
|
||||
if lockflag == "unlock":
|
||||
self.lock_state = 3
|
||||
self.critical_lock_state = 1
|
||||
elif lockflag == "lock":
|
||||
self.lock_state = 1
|
||||
self.critical_lock_state = 0
|
||||
self.seccfg_ver = 4
|
||||
self.seccfg_size = 0x3C
|
||||
self.sboot_runtime = 0
|
||||
seccfg_data = pack("<IIIIIII", self.magic, self.seccfg_ver, self.seccfg_size, self.lock_state,
|
||||
self.critical_lock_state, self.sboot_runtime, 0x45454545)
|
||||
dec_hash = hashlib.sha256(seccfg_data).digest()
|
||||
if locktype == "sw":
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_sw(dec_hash, True)
|
||||
else:
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_hw(dec_hash, True)
|
||||
self.hash = enc_hash
|
||||
data = seccfg_data + enc_hash
|
||||
data += b"\x00" * (0x200 - len(data))
|
||||
return bytearray(data)
|
||||
|
||||
|
||||
class xflashext(metaclass=LogBase):
|
||||
def __init__(self, mtk, xflash, loglevel):
|
||||
self.pathconfig = pathconfig()
|
||||
self.__logger = logsetup(self, self.__logger, loglevel)
|
||||
self.info = self.__logger.info
|
||||
self.debug = self.__logger.debug
|
||||
self.error = self.__logger.error
|
||||
self.warning = self.__logger.warning
|
||||
self.mtk = mtk
|
||||
self.loglevel = loglevel
|
||||
self.__logger = self.__logger
|
||||
self.eh = ErrorHandler()
|
||||
self.config = self.mtk.config
|
||||
self.usbwrite = self.mtk.port.usbwrite
|
||||
self.usbread = self.mtk.port.usbread
|
||||
self.echo = self.mtk.port.echo
|
||||
self.rbyte = self.mtk.port.rbyte
|
||||
self.rdword = self.mtk.port.rdword
|
||||
self.rword = self.mtk.port.rword
|
||||
self.xflash = xflash
|
||||
self.xsend = self.xflash.xsend
|
||||
self.send_devctrl = self.xflash.send_devctrl
|
||||
self.xread = self.xflash.xread
|
||||
self.status = self.xflash.status
|
||||
self.da2 = None
|
||||
self.da2address = None
|
||||
|
||||
def patch(self):
|
||||
self.da2 = self.xflash.daconfig.da2
|
||||
self.da2address = self.xflash.daconfig.da[3]["m_start_addr"] # at_address
|
||||
daextensions = os.path.join(self.pathconfig.get_payloads_path(), "da_x.bin")
|
||||
if os.path.exists(daextensions):
|
||||
daextdata = bytearray(open(daextensions, "rb").read())
|
||||
# open("out" + hex(self.da2address) + ".da", "wb").write(da2)
|
||||
register_cmd = find_binary(self.da2, b"\x38\xB5\x05\x46\x0C\x20")
|
||||
# sec_enc_seccfg = find_binary(self.da2, b"\x0E\x4B\x70\xB5\x06\x46")
|
||||
mmc_get_card = find_binary(self.da2, b"\x4B\x4F\xF4\x3C\x72")
|
||||
if mmc_get_card is not None:
|
||||
mmc_get_card -= 1
|
||||
else:
|
||||
mmc_get_card = find_binary(self.da2, b"\xA3\xEB\x00\x13\x18\x1A\x02\xEB\x00\x10")
|
||||
if mmc_get_card is not None:
|
||||
mmc_get_card -= 10
|
||||
mmc_set_part_config = find_binary(self.da2, b"\xC3\x69\x0A\x46\x10\xB5")
|
||||
if mmc_set_part_config is None:
|
||||
mmc_set_part_config = find_binary(self.da2, b"\xC3\x69\x13\xF0\x01\x03")
|
||||
mmc_rpmb_send_command = find_binary(self.da2, b"\xF8\xB5\x06\x46\x9D\xF8\x18\x50")
|
||||
if mmc_rpmb_send_command is None:
|
||||
mmc_rpmb_send_command = find_binary(self.da2, b"\x2D\xE9\xF0\x41\x4F\xF6\xFD\x74")
|
||||
|
||||
register_ptr = daextdata.find(b"\x11\x11\x11\x11")
|
||||
mmc_get_card_ptr = daextdata.find(b"\x22\x22\x22\x22")
|
||||
mmc_set_part_config_ptr = daextdata.find(b"\x33\x33\x33\x33")
|
||||
mmc_rpmb_send_command_ptr = daextdata.find(b"\x44\x44\x44\x44")
|
||||
ufshcd_queuecommand_ptr = daextdata.find(b"\x55\x55\x55\x55")
|
||||
ufshcd_get_free_tag_ptr = daextdata.find(b"\x66\x66\x66\x66")
|
||||
ptr_g_ufs_hba_ptr = daextdata.find(b"\x77\x77\x77\x77")
|
||||
|
||||
g_ufs_hba = None
|
||||
ptr_g_ufs_hba = find_binary(self.da2,b"\x20\x46\x0B\xB0\xBD\xE8\xF0\x83\x00\xBF")
|
||||
if ptr_g_ufs_hba is None:
|
||||
ptr_g_ufs_hba = find_binary(self.da2, b"\x21\x46\x02\xF0\x02\xFB\x1B\xE6\x00\xBF")
|
||||
if ptr_g_ufs_hba is not None:
|
||||
g_ufs_hba = int.from_bytes(self.da2[ptr_g_ufs_hba + 10+0x8:ptr_g_ufs_hba + 10+0x8 + 4], 'little')
|
||||
else:
|
||||
g_ufs_hba = int.from_bytes(self.da2[ptr_g_ufs_hba + 10:ptr_g_ufs_hba + 10 + 4], 'little')
|
||||
#open("da2_"+hex(self.da2address)+".bin","wb").write(self.da2)
|
||||
if ptr_g_ufs_hba is not None:
|
||||
ufshcd_get_free_tag = find_binary(self.da2,b"\xB5.\xB1\x90\xF8")
|
||||
ufshcd_queuecommand = find_binary(self.da2,b"\x2D\xE9\xF8\x43\x01\x27")
|
||||
else:
|
||||
g_ufs_hba = None
|
||||
ufshcd_get_free_tag = None
|
||||
ufshcd_queuecommand = None
|
||||
|
||||
if register_ptr != -1 and mmc_get_card_ptr != -1:
|
||||
if register_cmd:
|
||||
register_cmd = register_cmd + self.da2address | 1
|
||||
else:
|
||||
register_cmd = 0
|
||||
if mmc_get_card:
|
||||
mmc_get_card = mmc_get_card + self.da2address | 1
|
||||
else:
|
||||
mmc_get_card = 0
|
||||
if mmc_set_part_config:
|
||||
mmc_set_part_config = mmc_set_part_config + self.da2address | 1
|
||||
else:
|
||||
mmc_set_part_config = 0
|
||||
if mmc_rpmb_send_command:
|
||||
mmc_rpmb_send_command = mmc_rpmb_send_command + self.da2address | 1
|
||||
else:
|
||||
mmc_rpmb_send_command = 0
|
||||
|
||||
if ufshcd_get_free_tag:
|
||||
ufshcd_get_free_tag = ufshcd_get_free_tag + (self.da2address - 1) | 1
|
||||
else:
|
||||
ufshcd_get_free_tag = 0
|
||||
|
||||
if ufshcd_queuecommand:
|
||||
ufshcd_queuecommand = ufshcd_queuecommand + self.da2address | 1
|
||||
else:
|
||||
ufshcd_queuecommand = 0
|
||||
|
||||
if g_ufs_hba is None:
|
||||
g_ufs_hba = 0
|
||||
|
||||
# Patch the addr
|
||||
daextdata[register_ptr:register_ptr + 4] = pack("<I", register_cmd)
|
||||
daextdata[mmc_get_card_ptr:mmc_get_card_ptr + 4] = pack("<I", mmc_get_card)
|
||||
daextdata[mmc_set_part_config_ptr:mmc_set_part_config_ptr+4] = pack("<I",mmc_set_part_config)
|
||||
daextdata[mmc_rpmb_send_command_ptr:mmc_rpmb_send_command_ptr+4] = pack("<I",mmc_rpmb_send_command)
|
||||
daextdata[ufshcd_get_free_tag_ptr:ufshcd_get_free_tag_ptr + 4] = pack("<I", ufshcd_get_free_tag)
|
||||
daextdata[ufshcd_queuecommand_ptr:ufshcd_queuecommand_ptr + 4] = pack("<I", ufshcd_queuecommand)
|
||||
daextdata[ptr_g_ufs_hba_ptr:ptr_g_ufs_hba_ptr + 4] = pack("<I", g_ufs_hba)
|
||||
|
||||
# print(hexlify(daextdata).decode('utf-8'))
|
||||
#open("daext.bin","wb").write(daextdata)
|
||||
return daextdata
|
||||
return None
|
||||
|
||||
def patch_da2(self, da2):
|
||||
da2patched = bytearray(da2)
|
||||
# Patch security
|
||||
is_security_enabled = find_binary(da2, b"\x01\x23\x03\x60\x00\x20\x70\x47")
|
||||
if is_security_enabled != -1:
|
||||
da2patched[is_security_enabled:is_security_enabled + 2] = b"\x00\x23"
|
||||
# Patch hash check
|
||||
authaddr = find_binary(da2, b"\x04\x00\x07\xC0")
|
||||
if authaddr:
|
||||
da2patched[authaddr:authaddr + 4] = b"\x00\x00\x00\x00"
|
||||
elif authaddr is None:
|
||||
authaddr = find_binary(da2, b"\x4F\xF0\x04\x09\xCC\xF2\x07\x09")
|
||||
if authaddr:
|
||||
da2patched[authaddr:authaddr + 8] = b"\x4F\xF0\x00\x09\x4F\xF0\x00\x09"
|
||||
|
||||
# Patch write not allowed
|
||||
open("da2.bin","wb").write(da2patched)
|
||||
idx = 0
|
||||
while idx != -1:
|
||||
idx = da2patched.find(b"\x37\xB5\x00\x23\x04\x46\x02\xA8")
|
||||
if idx != -1:
|
||||
da2patched[idx:idx + 8] = b"\x37\xB5\x00\x20\x03\xB0\x30\xBD"
|
||||
|
||||
return da2patched
|
||||
|
||||
def fix_hash(self, da1, da2, hashpos, hashmode):
|
||||
da1 = bytearray(da1)
|
||||
dahash = None
|
||||
if hashmode == 1:
|
||||
dahash = hashlib.sha1(da2).digest()
|
||||
elif hashmode == 2:
|
||||
dahash = hashlib.sha256(da2).digest()
|
||||
da1[hashpos:hashpos + len(dahash)] = dahash
|
||||
return da1
|
||||
|
||||
def cmd(self, cmd):
|
||||
if self.xsend(self.xflash.Cmd.DEVICE_CTRL):
|
||||
status = self.status()
|
||||
if status == 0x0:
|
||||
if self.xsend(cmd):
|
||||
status = self.status()
|
||||
if status == 0x0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def custom_read(self, addr, length):
|
||||
if self.cmd(XCmd.CUSTOM_READ):
|
||||
self.xsend(addr)
|
||||
self.xsend(length)
|
||||
data = self.xread()
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return data
|
||||
return b""
|
||||
|
||||
def custom_write(self, addr, data):
|
||||
if self.cmd(XCmd.CUSTOM_WRITE):
|
||||
self.xsend(addr)
|
||||
self.xsend(len(data))
|
||||
self.xsend(data)
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def custom_writeregister(self, addr, data):
|
||||
if self.cmd(XCmd.CUSTOM_WRITEREGISTER):
|
||||
self.xsend(addr)
|
||||
self.xsend(data)
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def readmem(self, addr, dwords=1):
|
||||
res = []
|
||||
for pos in range(dwords):
|
||||
val = self.custom_read(addr + pos * 4, 4)
|
||||
if val == b"":
|
||||
return False
|
||||
data = unpack("<I", val)[0]
|
||||
if dwords == 1:
|
||||
return data
|
||||
res.append(data)
|
||||
return res
|
||||
|
||||
def writeregister(self, addr, dwords):
|
||||
if isinstance(dwords, int):
|
||||
dwords = [dwords]
|
||||
pos = 0
|
||||
for val in dwords:
|
||||
if not self.custom_writeregister(addr + pos, val):
|
||||
return False
|
||||
pos += 4
|
||||
return True
|
||||
|
||||
def writemem(self, addr, data):
|
||||
for i in range(0, len(data), 4):
|
||||
value = data[i:i + 4]
|
||||
while len(value) < 4:
|
||||
value += b"\x00"
|
||||
self.writeregister(addr + i, unpack("<I", value))
|
||||
return True
|
||||
|
||||
def custom_rpmb_read(self, sector, ufs=False):
|
||||
cmd=XCmd.CUSTOM_READ_RPMB
|
||||
if ufs:
|
||||
cmd=XCmd.CUSTOM_READ_UFS_RPMB
|
||||
if self.cmd(cmd):
|
||||
self.xsend(sector)
|
||||
status = unpack("<H", self.xread())[0]
|
||||
if status == 0x0:
|
||||
data = self.xread()
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return data
|
||||
return b''
|
||||
|
||||
def custom_rpmb_write(self, sector, data: bytes, ufs=False):
|
||||
if len(data) != 0x100:
|
||||
self.error("Incorrect rpmb frame length. Aborting")
|
||||
return False
|
||||
cmd=XCmd.CUSTOM_WRITE_RPMB
|
||||
if ufs:
|
||||
cmd=XCmd.CUSTOM_WRITE_UFS_RPMB
|
||||
if self.cmd(cmd):
|
||||
self.xsend(sector)
|
||||
self.xsend(data[:0x100])
|
||||
resp = unpack("<H", self.xread())[0]
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return resp
|
||||
return False
|
||||
|
||||
def custom_rpmb_init(self, ufs=False):
|
||||
cmd=XCmd.CUSTOM_INIT_RPMB
|
||||
if ufs:
|
||||
cmd=XCmd.CUSTOM_INIT_UFS_RPMB
|
||||
if self.cmd(cmd):
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def read_rpmb(self, filename=None, display=True):
|
||||
progressbar = progress(1)
|
||||
sectors = 0
|
||||
ufs = False
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
ufs = False
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
ufs = True
|
||||
if filename is None:
|
||||
filename = "rpmb.bin"
|
||||
if sectors > 0:
|
||||
with open(filename, "wb") as wf:
|
||||
for sector in range(sectors):
|
||||
if display:
|
||||
progressbar.show_progress("RPMB", sector, sectors, display)
|
||||
data = self.custom_rpmb_read(sector=sector,ufs=ufs)
|
||||
if data == b"":
|
||||
self.error("Couldn't read rpmb.")
|
||||
return False
|
||||
wf.write(data)
|
||||
self.info("Done reading rpmb to " + filename)
|
||||
return True
|
||||
return False
|
||||
|
||||
def write_rpmb(self, filename=None, display=True):
|
||||
progressbar = progress(1)
|
||||
if filename is None:
|
||||
self.error("Filename has to be given for writing to rpmb")
|
||||
return False
|
||||
if not os.path.exists(filename):
|
||||
self.error(f"Couldn't find {filename} for writing to rpmb.")
|
||||
return False
|
||||
ufs = False
|
||||
sectors = 0
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
ufs = False
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
ufs = True
|
||||
if self.custom_rpmb_init():
|
||||
if sectors > 0:
|
||||
with open(filename, "rb") as rf:
|
||||
for sector in range(sectors):
|
||||
if display:
|
||||
progressbar.show_progress("RPMB", sector, sectors, display)
|
||||
if not self.custom_rpmb_write(sector=sector, data=rf.read(0x100), ufs=ufs):
|
||||
self.error(f"Couldn't write rpmb at sector {sector}.")
|
||||
return False
|
||||
self.info(f"Done reading writing {filename} to rpmb")
|
||||
return True
|
||||
return False
|
||||
|
||||
def cryptosetup(self):
|
||||
setup = crypto_setup()
|
||||
setup.blacklist = self.config.chipconfig.blacklist
|
||||
setup.gcpu_base = self.config.chipconfig.gcpu_base
|
||||
setup.dxcc_base = self.config.chipconfig.dxcc_base
|
||||
setup.da_payload_addr = self.config.chipconfig.da_payload_addr
|
||||
setup.sej_base = self.config.chipconfig.sej_base
|
||||
setup.read32 = self.readmem
|
||||
setup.write32 = self.writeregister
|
||||
setup.writemem = self.writemem
|
||||
return hwcrypto(setup, self.loglevel)
|
||||
|
||||
def seccfg(self, lockflag):
|
||||
if lockflag not in ["unlock", "lock"]:
|
||||
print("Valid flags are: unlock, lock")
|
||||
return False
|
||||
hwc = self.cryptosetup()
|
||||
sc_org = seccfg(hwc)
|
||||
data, guid_gpt = self.xflash.partition.get_gpt(0, 0, 0, "user")
|
||||
seccfg_data = None
|
||||
partition = None
|
||||
for rpartition in guid_gpt.partentries:
|
||||
if rpartition.name == "seccfg":
|
||||
partition = rpartition
|
||||
seccfg_data = self.xflash.readflash(
|
||||
addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=partition.sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
filename="", parttype="user", display=False)
|
||||
break
|
||||
if seccfg_data is None:
|
||||
self.error("Couldn't detect existing seccfg partition. Aborting unlock.")
|
||||
return False
|
||||
if seccfg_data[:4] != pack("<I", 0x4D4D4D4D):
|
||||
self.error("Unknown seccfg partition header. Aborting unlock.")
|
||||
return False
|
||||
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False
|
||||
sc_new = seccfg(hwc)
|
||||
if lockflag == "unlock":
|
||||
prelock = "lock"
|
||||
else:
|
||||
prelock = "unlock"
|
||||
hwtype = "hw"
|
||||
sc_new.create(prelock, hwtype)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
hwtype = "sw"
|
||||
sc_new.create(prelock, hwtype)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
self.error("Device has is either already unlocked or algo is unknown. Aborting.")
|
||||
return False
|
||||
writedata = sc_new.create(lockflag, hwtype)
|
||||
if self.xflash.writeflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=len(writedata),
|
||||
filename=None, wdata=writedata, parttype="user", display=True):
|
||||
self.info("Successfully wrote seccfg.")
|
||||
return True
|
||||
self.error("Error on writing seccfg config to flash.")
|
||||
return False
|
||||
|
||||
def generate_keys(self):
|
||||
hwc = self.cryptosetup()
|
||||
meid = b""
|
||||
if os.path.exists(os.path.join("logs", "meid.txt")):
|
||||
meid = bytes.fromhex(open(os.path.join("logs", "meid.txt"), "r").read())
|
||||
self.info("MEID : " + hexlify(meid).decode('utf-8'))
|
||||
if os.path.exists(os.path.join("logs", "socid.txt")):
|
||||
socid = bytes.fromhex(open(os.path.join("logs", "socid.txt"), "r").read())
|
||||
self.info("SOCID : " + hexlify(socid).decode('utf-8'))
|
||||
if self.config.chipconfig.dxcc_base is not None:
|
||||
self.info("Generating dxcc rpmbkey...")
|
||||
rpmbkey = hwc.aes_hwcrypt(btype="dxcc", mode="rpmb")
|
||||
self.info("Generating dxcc fdekey...")
|
||||
fdekey = hwc.aes_hwcrypt(btype="dxcc", mode="fde")
|
||||
self.info("Generating dxcc rpmbkey2...")
|
||||
rpmb2key = hwc.aes_hwcrypt(btype="dxcc", mode="rpmb2")
|
||||
self.info("Generating dxcc itrustee key...")
|
||||
ikey = hwc.aes_hwcrypt(btype="dxcc", mode="itrustee")
|
||||
|
||||
if rpmbkey is not None:
|
||||
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8'))
|
||||
open(os.path.join("logs", "rpmbkey.txt"), "wb").write(hexlify(rpmbkey))
|
||||
if rpmb2key is not None:
|
||||
self.info("RPMB2 : " + hexlify(rpmb2key).decode('utf-8'))
|
||||
open(os.path.join("logs", "rpmb2key.txt"), "wb").write(hexlify(rpmb2key))
|
||||
if fdekey is not None:
|
||||
self.info("FDE : " + hexlify(fdekey).decode('utf-8'))
|
||||
open(os.path.join("logs", "fdekey.txt"), "wb").write(hexlify(fdekey))
|
||||
if ikey is not None:
|
||||
self.info("iTrustee : " + hexlify(ikey).decode('utf-8'))
|
||||
open(os.path.join("logs", "itrustee_fbe.txt"), "wb").write(hexlify(ikey))
|
||||
"""
|
||||
hrid = self.xflash.get_hrid()
|
||||
if hrid is not None:
|
||||
self.info("HRID : " + hexlify(hrid).decode('utf-8'))
|
||||
open(os.path.join("logs", "hrid.txt"), "wb").write(hexlify(hrid))
|
||||
"""
|
||||
elif self.config.chipconfig.sej_base is not None:
|
||||
if meid != b"":
|
||||
self.info("Generating sej rpmbkey...")
|
||||
otp = None
|
||||
if self.mtk.config.preloader is not None:
|
||||
idx = self.mtk.config.preloader.find(b"\x4D\x4D\x4D\x01\x30")
|
||||
if idx != -1:
|
||||
otp = self.mtk.config.preloader[idx + 0xC:idx + 0xC + 32]
|
||||
if otp is None:
|
||||
otp = 32 * b"\x00"
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, otp=otp, btype="sej")
|
||||
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8'))
|
||||
open(os.path.join("logs", "rpmbkey.txt"), "wb").write(hexlify(rpmbkey))
|
||||
return True
|
Binary file not shown.
BIN
mtkclient/Loader/Preloader/0699_preloader_dura_BFE22C5E88.bin
Normal file
BIN
mtkclient/Loader/Preloader/0699_preloader_dura_BFE22C5E88.bin
Normal file
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/0766_preloader_cereus_3C2D76D046.bin
Normal file
BIN
mtkclient/Loader/Preloader/0766_preloader_cereus_3C2D76D046.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/0813_preloader_begonia_1547BE956A.bin
Normal file
BIN
mtkclient/Loader/Preloader/0813_preloader_begonia_1547BE956A.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/A15s_preloader_oppo6765.bin
Normal file
BIN
mtkclient/Loader/Preloader/A15s_preloader_oppo6765.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/A7x_preloader_oppo6771_18011.bin
Normal file
BIN
mtkclient/Loader/Preloader/A7x_preloader_oppo6771_18011.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/Coolpad_Cool_X_Preloader.bin
Normal file
BIN
mtkclient/Loader/Preloader/Coolpad_Cool_X_Preloader.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/F11_PRO_preloader_oppo6771_18531.bin
Normal file
BIN
mtkclient/Loader/Preloader/F11_PRO_preloader_oppo6771_18531.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/OPPO_A3_preloader_oppo6771_17331.bin
Normal file
BIN
mtkclient/Loader/Preloader/OPPO_A3_preloader_oppo6771_17331.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/OPPO_A91_preloader_oppo6771_19350.bin
Normal file
BIN
mtkclient/Loader/Preloader/OPPO_A91_preloader_oppo6771_19350.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/Realme_3_preloader_oppo6771_18601.bin
Normal file
BIN
mtkclient/Loader/Preloader/Realme_3_preloader_oppo6771_18601.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/alcatel_OT-5028A_preloader.bin
Normal file
BIN
mtkclient/Loader/Preloader/alcatel_OT-5028A_preloader.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_A45.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_A45.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_A7L6_b1-770.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_A7L6_b1-770.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_A8_b1-850.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_A8_b1-850.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_AC156OXYGEN.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_AC156OXYGEN.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_Archos_101e_neon.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_Archos_101e_neon.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_E286L.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_E286L.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_G10_if.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_G10_if.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_K711C.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_K711C.bin
Normal file
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_K802.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_K802.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_M013F_U1.img
Normal file
BIN
mtkclient/Loader/Preloader/preloader_M013F_U1.img
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_MMX_6750_66_n.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_MMX_6750_66_n.bin
Normal file
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_Moto_6737_wt98737.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_Moto_6737_wt98737.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_P98995AA1.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_P98995AA1.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mtkclient/Loader/Preloader/preloader_S11Pro.bin
Normal file
BIN
mtkclient/Loader/Preloader/preloader_S11Pro.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue