mirror of
https://github.com/bkerler/edl.git
synced 2024-11-24 00:17:52 -05:00
Add support for Nothing Phones, add support for qc sahara v3
This commit is contained in:
parent
356ab5e3a2
commit
a411f608ff
10 changed files with 332 additions and 180 deletions
72
edl
72
edl
|
@ -14,14 +14,14 @@ Usage:
|
|||
edl [--debugmode] [--portname=portname] [--serial]
|
||||
edl [--gpt-num-part-entries=number] [--gpt-part-entry-size=number] [--gpt-part-entry-start-lba=number] [--portname=portname] [--serial]
|
||||
edl [--memory=memtype] [--skipstorageinit] [--maxpayload=bytes] [--sectorsize==bytes] [--portname=portname] [--serial]
|
||||
edl server [--tcpport=portnumber] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl server [--tcpport=portnumber] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl memorydump [--partitions=partnames] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--serial_number=serial_number]
|
||||
edl printgpt [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl gpt <directory> [--memory=memtype] [--lun=lun] [--genxml] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl r <partitionname> <filename> [--memory=memtype] [--sectorsize==bytes] [--lun=lun] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl rl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--genxml] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl rf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl rs <start_sector> <sectors> <filename> [--lun=lun] [--sectorsize==bytes] [--memory=memtype] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl printgpt [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl gpt <directory> [--memory=memtype] [--lun=lun] [--genxml] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl r <partitionname> <filename> [--memory=memtype] [--sectorsize==bytes] [--lun=lun] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl rl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--genxml] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl rf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl rs <start_sector> <sectors> <filename> [--lun=lun] [--sectorsize==bytes] [--memory=memtype] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl w <partitionname> <filename> [--partitionfilename=filename] [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skipwrite] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl wl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl wf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
|
@ -29,7 +29,7 @@ Usage:
|
|||
edl e <partitionname> [--memory=memtype] [--skipwrite] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl es <start_sector> <sectors> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skipwrite] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl ep <partitionname> <sectors> [--memory=memtype] [--skipwrite] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl footer <filename> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl footer <filename> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl peek <offset> <length> <filename> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl peekhex <offset> <length> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl peekdword <offset> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
|
@ -43,17 +43,17 @@ Usage:
|
|||
edl secureboot [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl pbl <filename> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl qfp <filename> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl getstorageinfo [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl setbootablestoragedrive <lun> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl setactiveslot <slot> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl send <command> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl xml <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl rawxml <xmlstring> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl reset [--resetmode=mode] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl nop [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
|
||||
edl getstorageinfo [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl setbootablestoragedrive <lun> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl setactiveslot <slot> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl send <command> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl xml <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl rawxml <xmlstring> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl reset [--resetmode=mode] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl nop [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl modules <command> <options> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--portname=portname] [--serial]
|
||||
edl provision <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl qfil <rawprogram> <patch> <imagedir> [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
|
||||
edl provision <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
edl qfil <rawprogram> <patch> <imagedir> [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
|
||||
|
||||
Description:
|
||||
server # Run tcp/ip server
|
||||
|
@ -147,7 +147,7 @@ from binascii import hexlify
|
|||
|
||||
args = docopt(__doc__, version='3')
|
||||
|
||||
print("Qualcomm Sahara / Firehose Client V3.61 (c) B.Kerler 2018-2023.")
|
||||
print("Qualcomm Sahara / Firehose Client V3.62 (c) B.Kerler 2018-2023.")
|
||||
|
||||
|
||||
def parse_cmd(rargs):
|
||||
|
@ -232,26 +232,6 @@ class main(metaclass=LogBase):
|
|||
self.cdc.close()
|
||||
sys.exit()
|
||||
|
||||
def handle_streaming(self, mode):
|
||||
self.cdc.timeout = None
|
||||
sahara_info = self.sahara.streaminginfo()
|
||||
if sahara_info:
|
||||
mode, resp = self.sahara.connect()
|
||||
if mode == "sahara":
|
||||
mode = self.sahara.upload_loader()
|
||||
if "enprg" in self.sahara.programmer.lower():
|
||||
mode = "load_enandprg"
|
||||
elif "nprg" in self.sahara.programmer.lower():
|
||||
mode = "load_nandprg"
|
||||
elif mode != "":
|
||||
mode = "load_" + mode
|
||||
if "load_" in mode:
|
||||
time.sleep(0.3)
|
||||
else:
|
||||
print("Error, couldn't find suitable enprg/nprg loader :(")
|
||||
self.exit()
|
||||
return mode
|
||||
|
||||
def run(self):
|
||||
if is_windows():
|
||||
proper_driver = console_cmd(r'reg query HKLM\HARDWARE\DEVICEMAP\SERIALCOMM')
|
||||
|
@ -308,6 +288,10 @@ class main(metaclass=LogBase):
|
|||
self.cdc.timeout = 1500
|
||||
conninfo = self.doconnect(loop)
|
||||
mode = conninfo["mode"]
|
||||
if not "data" in conninfo:
|
||||
version = 2
|
||||
else:
|
||||
version = conninfo["data"].version
|
||||
if mode == "sahara":
|
||||
cmd = conninfo["cmd"]
|
||||
if cmd == cmd_t.SAHARA_HELLO_REQ:
|
||||
|
@ -318,9 +302,9 @@ class main(metaclass=LogBase):
|
|||
time.sleep(0.5)
|
||||
print("Device is in memory dump mode, dumping memory")
|
||||
if args["--partitions"]:
|
||||
self.sahara.debug_mode(args["--partitions"].split(","))
|
||||
self.sahara.debug_mode(args["--partitions"].split(","),version=version)
|
||||
else:
|
||||
self.sahara.debug_mode()
|
||||
self.sahara.debug_mode(version=version)
|
||||
self.exit()
|
||||
else:
|
||||
print("Device is in streaming mode, uploading loader")
|
||||
|
@ -333,7 +317,7 @@ class main(metaclass=LogBase):
|
|||
else:
|
||||
mode, resp = sahara_connect
|
||||
if mode == "sahara":
|
||||
mode = self.sahara.upload_loader()
|
||||
mode = self.sahara.upload_loader(version=version)
|
||||
if "enprg" in self.sahara.programmer.lower():
|
||||
mode = "load_enandprg"
|
||||
elif "nprg" in self.sahara.programmer.lower():
|
||||
|
@ -346,14 +330,14 @@ class main(metaclass=LogBase):
|
|||
print("Error, couldn't find suitable enprg/nprg loader :(")
|
||||
self.exit()
|
||||
else:
|
||||
sahara_info = self.sahara.cmd_info()
|
||||
sahara_info = self.sahara.cmd_info(version=version)
|
||||
if sahara_info is not None:
|
||||
resp = self.sahara.connect()
|
||||
mode = resp["mode"]
|
||||
if "data" in resp:
|
||||
data = resp["data"]
|
||||
if mode == "sahara":
|
||||
mode = self.sahara.upload_loader()
|
||||
mode = self.sahara.upload_loader(version=version)
|
||||
else:
|
||||
print("Error on sahara handshake, resetting.")
|
||||
self.sahara.cmd_reset()
|
||||
|
|
|
@ -12,24 +12,32 @@ from edlclient.Library.utils import LogBase
|
|||
try:
|
||||
from edlclient.Library.Modules.generic import generic
|
||||
except ImportError as e:
|
||||
print(e)
|
||||
generic = None
|
||||
pass
|
||||
|
||||
try:
|
||||
from edlclient.Library.Modules.oneplus import oneplus
|
||||
except ImportError as e:
|
||||
print(e)
|
||||
oneplus = None
|
||||
pass
|
||||
|
||||
try:
|
||||
from edlclient.Library.Modules.xiaomi import xiaomi
|
||||
except ImportError as e:
|
||||
print(e)
|
||||
xiaomi = None
|
||||
pass
|
||||
|
||||
try:
|
||||
from edlclient.Library.Modules.nothing import nothing
|
||||
except ImportError as e:
|
||||
nothing = None
|
||||
pass
|
||||
|
||||
class modules(metaclass=LogBase):
|
||||
def __init__(self, fh, serial, supported_functions, loglevel, devicemodel, args):
|
||||
def __init__(self, fh, serial:int, supported_functions, loglevel, devicemodel:str, args):
|
||||
self.fh = fh
|
||||
self.args = args
|
||||
self.serial = serial
|
||||
|
@ -47,17 +55,20 @@ class modules(metaclass=LogBase):
|
|||
try:
|
||||
self.generic = generic(fh=self.fh, serial=self.serial, args=self.args, loglevel=loglevel)
|
||||
except Exception as e:
|
||||
self.error(e)
|
||||
pass
|
||||
self.ops = None
|
||||
try:
|
||||
self.ops = oneplus(fh=self.fh, projid=self.devicemodel, serial=self.serial,
|
||||
supported_functions=self.supported_functions, args=self.args, loglevel=loglevel)
|
||||
except Exception as e:
|
||||
self.error(e)
|
||||
pass
|
||||
self.xiaomi = None
|
||||
try:
|
||||
self.xiaomi = xiaomi(fh=self.fh)
|
||||
except Exception as e:
|
||||
self.error(e)
|
||||
pass
|
||||
|
||||
def addpatch(self):
|
||||
|
|
65
edlclient/Library/Modules/nothing.py
Normal file
65
edlclient/Library/Modules/nothing.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) B.Kerler 2018-2023 under GPLv3 license
|
||||
# If you use my code, make sure you refer to my name
|
||||
#
|
||||
# !!!!! If you use this code in commercial products, your product is automatically
|
||||
# GPLv3 and has to be open sourced under GPLv3 as well. !!!!!
|
||||
import hashlib
|
||||
import logging
|
||||
import random
|
||||
|
||||
from edlclient.Library.utils import LogBase
|
||||
|
||||
|
||||
class nothing(metaclass=LogBase):
|
||||
def __init__(self, fh, projid="22111", serial=123456, ATOBuild=0, Flash_Mode=0, cf=0, supported_functions=None,
|
||||
loglevel=logging.INFO):
|
||||
self.fh = fh
|
||||
self.projid = projid
|
||||
#self.projid == "22111":
|
||||
self.hashverify = "16386b4035411a770b12507b2e30297c0c5471230b213e6a1e1e701c6a425150"
|
||||
self.serial = serial
|
||||
self.supported_functions = supported_functions
|
||||
self.__logger.setLevel(loglevel)
|
||||
if loglevel == logging.DEBUG:
|
||||
logfilename = "log.txt"
|
||||
fh = logging.FileHandler(logfilename)
|
||||
self.__logger.addHandler(fh)
|
||||
|
||||
def generatetoken(self, token1: str = None):
|
||||
if token1 is None:
|
||||
token1 = random.randbytes(32).hex()
|
||||
authresp = token1 + self.projid + ("%x" % self.serial) + self.hashverify
|
||||
token2 = hashlib.sha256(bytes(authresp,'utf-8')).hexdigest()[:64]
|
||||
token3 = self.hashverify
|
||||
return bytes(f"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>\n <ntprojectverify token1=\"{token1}\" token2=\"{token2}\" token3=\"{token3}\"/>\n</data>\n",'utf-8')
|
||||
|
||||
|
||||
def ntprojectverify(self):
|
||||
"""
|
||||
Nothing Phone 2
|
||||
"""
|
||||
authcmd = b"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>\n <checkntfeature />\n</data>\n"
|
||||
rsp = self.fh.xmlsend(authcmd)
|
||||
if rsp.resp:
|
||||
authresp = self.generatetoken()
|
||||
rsp = self.fh.xmlsend(authresp)
|
||||
if rsp.resp:
|
||||
if b"ACK" in rsp.data:
|
||||
return True
|
||||
if "value" in rsp.resp:
|
||||
if rsp.resp["value"] == "ACK":
|
||||
if 'authenticated' in rsp.log[0].lower() and 'true' in rsp.log[0].lower():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
nt = nothing(fh=None, projid="22111", serial=1729931115)
|
||||
res=nt.generatetoken(token1="512034500a07154561661e0f371f4a712a0b76074605724c640e301d632b3671")
|
||||
org=b"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>\n <ntprojectverify token1=\"512034500a07154561661e0f371f4a712a0b76074605724c640e301d632b3671\" token2=\"1ecd222465436eb8acc0cfc41e90d1e677165c184ea7d9631615014dac88c669\" token3=\"16386b4035411a770b12507b2e30297c0c5471230b213e6a1e1e701c6a425150\"/>\n</data>\n"
|
||||
if res!=org:
|
||||
print("Error !")
|
||||
print(res)
|
||||
print(nt.generatetoken())
|
|
@ -24,7 +24,7 @@ import random
|
|||
from struct import pack
|
||||
import logging
|
||||
from edlclient.Library.utils import LogBase
|
||||
|
||||
from edlclient.Library.Modules.oneplus_param import paramtools
|
||||
try:
|
||||
from edlclient.Library.cryptutils import cryptutils
|
||||
except Exception as e:
|
||||
|
@ -128,7 +128,7 @@ deviceconfig = {
|
|||
|
||||
|
||||
class oneplus(metaclass=LogBase):
|
||||
def __init__(self, fh, projid="18825", serial=123456, ATOBuild=0, Flash_Mode=0, cf=0, supported_functions=None,
|
||||
def __init__(self, fh, projid:str="18825", serial=123456, ATOBuild=0, Flash_Mode=0, cf=0, supported_functions=None,
|
||||
args=None, loglevel=logging.INFO):
|
||||
self.fh = fh
|
||||
self.__logger = self.__logger
|
||||
|
@ -160,7 +160,6 @@ class oneplus(metaclass=LogBase):
|
|||
filehandler = logging.FileHandler(logfilename)
|
||||
self.__logger.addHandler(filehandler)
|
||||
try:
|
||||
from edlclient.Library.Modules.oneplus_param import paramtools
|
||||
if projid in deviceconfig:
|
||||
mode = deviceconfig[projid]["param_mode"]
|
||||
self.ops_parm = paramtools(mode=mode, serial=serial)
|
||||
|
@ -200,10 +199,11 @@ class oneplus(metaclass=LogBase):
|
|||
exit(0)
|
||||
elif version == 3:
|
||||
if cm is not None:
|
||||
oneplus2(fh, cm, serial, pk, prodkey, self.ATOBuild, self.Flash_Mode, self.cf)
|
||||
return oneplus2(fh, cm, serial, pk, prodkey, self.ATOBuild, self.Flash_Mode, self.cf)
|
||||
else:
|
||||
assert "Device is not supported"
|
||||
exit(0)
|
||||
assert "Unknown projid:"+str(projid)
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
|
@ -225,16 +225,16 @@ class oneplus(metaclass=LogBase):
|
|||
if self.ops.setprojmodel_verify:
|
||||
return self.ops.setprojmodel_verify(pk, token)
|
||||
|
||||
def setswprojmodel_verify(self, pk, token, device_timestamp):
|
||||
def setswprojmodel_verify(self, pk, token):
|
||||
if self.ops.setswprojmodel_verify:
|
||||
return self.ops.setswprojmodel_verify(pk, token, device_timestamp)
|
||||
return self.ops.setswprojmodel_verify(pk, token)
|
||||
|
||||
def program_verify(self, pk, token, tokendata):
|
||||
if self.ops.program_verify:
|
||||
return self.ops.program_verify(pk, token, tokendata)
|
||||
|
||||
def generatetoken(self, program=False, device_timestamp="123456789"):
|
||||
return self.ops.generatetoken(program=program, device_timestamp=device_timestamp)
|
||||
def generatetoken(self, program=False):
|
||||
return self.ops.generatetoken(program=program)
|
||||
|
||||
def demacia(self):
|
||||
if self.ops.demacia():
|
||||
|
@ -310,7 +310,7 @@ class oneplus1:
|
|||
data = "<?xml version=\"1.0\" ?>\n<data>\n<demacia token=\"" + token + "\" pk=\"" + pk + "\" />\n</data>"
|
||||
return data
|
||||
|
||||
def generatetoken(self, program=False, device_timestamp=None):
|
||||
def generatetoken(self, program=False):
|
||||
timestamp = str(int(time.time()))
|
||||
ha = cryptutils().hash()
|
||||
h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix
|
||||
|
@ -429,6 +429,7 @@ class oneplus1:
|
|||
class oneplus2(metaclass=LogBase):
|
||||
def __init__(self, fh, ModelVerifyPrjName="20889", serial=123456, pk="", prodkey="", ATOBuild=0, Flash_Mode=0,
|
||||
cf=0, loglevel=logging.INFO):
|
||||
self.device_timestamp = None
|
||||
self.ModelVerifyPrjName = ModelVerifyPrjName
|
||||
self.pk = pk
|
||||
self.fh = fh
|
||||
|
@ -445,10 +446,10 @@ class oneplus2(metaclass=LogBase):
|
|||
fh = logging.FileHandler(logfilename)
|
||||
self.__logger.addHandler(fh)
|
||||
|
||||
def crypt_token(self, data, pk, device_timestamp, decrypt=False):
|
||||
def crypt_token(self, data, pk, device_timestamp:int, decrypt=False):
|
||||
aes = cryptutils().aes()
|
||||
aeskey = b"\x46\xA5\x97\x30\xBB\x0D\x41\xE8" + bytes(pk, 'utf-8') + \
|
||||
pack("<Q", int(device_timestamp, 10)) # we get this using setprocstart
|
||||
pack("<Q", device_timestamp) # we get this using setprocstart
|
||||
aesiv = b"\xDC\x91\x0D\x88\xE3\xC6\xEE\x65\xF0\xC7\x44\xB4\x02\x30\xCE\x40"
|
||||
if decrypt:
|
||||
cdata = unhexlify(data)
|
||||
|
@ -463,7 +464,7 @@ class oneplus2(metaclass=LogBase):
|
|||
rdata = hexlify(result)
|
||||
return rdata.upper().decode('utf-8')
|
||||
|
||||
def generatetoken(self, program=False, device_timestamp=None): # setswprojmodel
|
||||
def generatetoken(self, program=False): # setswprojmodel
|
||||
timestamp = str(int(time.time()))
|
||||
ha = cryptutils().hash()
|
||||
h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix
|
||||
|
@ -482,7 +483,7 @@ class oneplus2(metaclass=LogBase):
|
|||
for item in items:
|
||||
data += item + ","
|
||||
data = data[:-1]
|
||||
token = self.crypt_token(data, self.pk, device_timestamp)
|
||||
token = self.crypt_token(data, self.pk, self.device_timestamp)
|
||||
return self.pk, token
|
||||
|
||||
def run(self, flag):
|
||||
|
@ -493,7 +494,9 @@ class oneplus2(metaclass=LogBase):
|
|||
return False
|
||||
data = res.decode('utf-8')
|
||||
device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1]
|
||||
pk, token = self.generatetoken(False, device_timestamp)
|
||||
self.device_timestamp = int(device_timestamp)
|
||||
print(self.device_timestamp)
|
||||
pk, token = self.generatetoken(False)
|
||||
res = self.fh.cmd_send(f"setswprojmodel token=\"{token}\" pk=\"{pk}\"")
|
||||
if not b"model_check=\"0\"" in res or not b"auth_token_verify=\"0\"" in res:
|
||||
print("Setswprojmodel failed.")
|
||||
|
@ -501,10 +504,10 @@ class oneplus2(metaclass=LogBase):
|
|||
return False
|
||||
return True
|
||||
|
||||
def setswprojmodel_verify(self, pk, token, device_timestamp):
|
||||
def setswprojmodel_verify(self, pk, token):
|
||||
self.pk = pk
|
||||
ha = cryptutils().hash()
|
||||
items = self.crypt_token(token, pk, device_timestamp, True)
|
||||
items = self.crypt_token(token, pk, self.device_timestamp, True)
|
||||
info = ["ModelVerifyPrjName", "random_postfix", "ModelVerifyHashToken", "ato_build_state", "flash_mode",
|
||||
"Version", "soc_sn", "cf", "timestamp", "secret"]
|
||||
i = 0
|
||||
|
@ -568,10 +571,11 @@ def main():
|
|||
serial = args["--serial"]
|
||||
device_timestamp = args["--ts"]
|
||||
op2 = oneplus(None, projid="20889", serial=serial, ATOBuild=0, Flash_Mode=0, cf=0)
|
||||
op2.ops.device_timestamp = int(device_timestamp)
|
||||
# 20889 OP N10 5G Europe
|
||||
print(f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setprocstart /></data>\"")
|
||||
# Response should be : <?xml version="1.0" ?><data><response value=1 device_timestamp="%llu" /></data>
|
||||
pk, token = op2.generatetoken(False, device_timestamp)
|
||||
pk, token = op2.generatetoken(False)
|
||||
print(
|
||||
f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setswprojmodel " +
|
||||
f"token=\\\"{token}\\\" pk=\\\"{pk}\\\" /></data>\" --debugmode")
|
||||
|
@ -605,9 +609,10 @@ def main():
|
|||
projid = args["--projid"][0]
|
||||
device_timestamp = args["--ts"]
|
||||
op = oneplus(None, projid=projid, serial=123456)
|
||||
op.ops.device_timestamp = int(device_timestamp)
|
||||
token = args["<token>"]
|
||||
pk = args["<pk>"]
|
||||
op.setswprojmodel_verify(pk, token, device_timestamp)
|
||||
op.setswprojmodel_verify(pk, token)
|
||||
|
||||
|
||||
def test_setswprojmodel_verify():
|
||||
|
@ -617,8 +622,9 @@ def test_setswprojmodel_verify():
|
|||
op = oneplus(None, projid=projid, serial=123456)
|
||||
data = deviceresp.decode('utf-8')
|
||||
device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1]
|
||||
pk, token = op.generatetoken(False, device_timestamp)
|
||||
if not op.setswprojmodel_verify(pk, token, device_timestamp):
|
||||
op.ops.device_timestamp = int(device_timestamp)
|
||||
pk, token = op.generatetoken(False)
|
||||
if not op.setswprojmodel_verify(pk, token):
|
||||
assert "Setswprojmodel error"
|
||||
|
||||
|
||||
|
|
|
@ -12,12 +12,10 @@ Usage:
|
|||
oneplus_param.py gencode <imei>
|
||||
oneplus_param.py setparam <filename> <sid> <offset> <value> [--mode=mode] [--serial=serial]
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from struct import calcsize, pack, unpack
|
||||
import hashlib
|
||||
import zlib
|
||||
import qrcode
|
||||
from enum import Enum
|
||||
from struct import calcsize, pack, unpack
|
||||
|
||||
try:
|
||||
from edlclient.Library.cryptutils import cryptutils
|
||||
|
@ -31,10 +29,6 @@ except ImportError as e:
|
|||
from cryptutils import cryptutils
|
||||
except ImportError as e:
|
||||
print(str(e))
|
||||
try:
|
||||
from edlclient.Library.Modules.oneplus_param import *
|
||||
except ImportError:
|
||||
pass
|
||||
from binascii import unhexlify, hexlify
|
||||
|
||||
|
||||
|
@ -984,6 +978,7 @@ def main():
|
|||
print("oneplus Factory qr code generator (c) B. Kerler 2019\nGPLv3 License\n----------------------")
|
||||
print("Code : *#*#5646#*#* , *#808#, *#36446337# = com.android.engineeringmode.manualtest.DecryptActivity")
|
||||
results = param.gencode([imei, "YOU_CAN_PASS_NOW"])
|
||||
import qrcode
|
||||
img = qrcode.make("op_eng://" + results[0])
|
||||
print("Code : " + results[0])
|
||||
img.save(imei + ".png")
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import binascii
|
||||
import io
|
||||
import os.path
|
||||
import platform
|
||||
import time
|
||||
import json
|
||||
|
@ -15,6 +16,8 @@ from struct import unpack
|
|||
from binascii import hexlify
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
|
||||
from edlclient.Library.Modules.nothing import nothing
|
||||
from edlclient.Library.utils import *
|
||||
from edlclient.Library.gpt import gpt
|
||||
from edlclient.Library.sparse import QCSparse
|
||||
|
@ -1031,6 +1034,15 @@ class firehose(metaclass=LogBase):
|
|||
self.cfg.SECTOR_SIZE_IN_BYTES = 4096
|
||||
return self.configure(0)
|
||||
self.parse_storage()
|
||||
for function in self.supported_functions:
|
||||
if function == "checkntfeature":
|
||||
if type(self.devicemodel)==list:
|
||||
self.devicemodel=self.devicemodel[0]
|
||||
self.nothing = nothing(fh=self, projid=self.devicemodel, serial=self.serial,
|
||||
supported_functions=self.supported_functions,
|
||||
loglevel=self.loglevel)
|
||||
if self.nothing is not None:
|
||||
self.nothing.ntprojectverify()
|
||||
self.luns = self.getluns(self.args)
|
||||
return True
|
||||
|
||||
|
@ -1127,6 +1139,8 @@ class firehose(metaclass=LogBase):
|
|||
if "chip serial num" in line.lower():
|
||||
try:
|
||||
serial = line.split("0x")[1][:-1]
|
||||
if ")" in serial:
|
||||
serial=serial[:serial.rfind(")")]
|
||||
self.serial = int(serial, 16)
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
self.debug(str(err))
|
||||
|
@ -1150,7 +1164,8 @@ class firehose(metaclass=LogBase):
|
|||
try:
|
||||
if os.path.exists(self.cfg.programmer):
|
||||
data = open(self.cfg.programmer, "rb").read()
|
||||
for cmd in [b"demacia", b"setprojmodel", b"setswprojmodel", b"setprocstart", b"SetNetType"]:
|
||||
for cmd in [b"demacia", b"setprojmodel", b"setswprojmodel", b"setprocstart", b"SetNetType",
|
||||
b"checkntfeature"]:
|
||||
if cmd in data:
|
||||
self.supported_functions.append(cmd.decode('utf-8'))
|
||||
state = {
|
||||
|
@ -1158,7 +1173,19 @@ class firehose(metaclass=LogBase):
|
|||
"programmer": self.cfg.programmer,
|
||||
"serial": self.serial
|
||||
}
|
||||
if os.path.exists("edl_config.json"):
|
||||
data = json.loads(open("edl_config.json","rb").read().decode('utf-8'))
|
||||
if "serial" in data and data["serial"]!=state["serial"]:
|
||||
open("edl_config.json", "w").write(json.dumps(state))
|
||||
else:
|
||||
self.supported_functions = data["supported_functions"]
|
||||
self.cfg.programmer = data["programmer"]
|
||||
else:
|
||||
open("edl_config.json", "w").write(json.dumps(state))
|
||||
if "001920e101cf0000_fa2836525c2aad8a_fhprg.bin" in self.cfg.programmer:
|
||||
self.devicemodel = '20111'
|
||||
elif "000b80e100020000_467f3020c4cc788d_fhprg.bin" in self.cfg.programmer:
|
||||
self.devicemodel = '22111'
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
|
@ -390,7 +390,7 @@ class gpt(metaclass=LogBase):
|
|||
if pa.type == "EFI_UNUSED":
|
||||
continue
|
||||
self.partentries[pa.name]=pa
|
||||
self.totalsectors = self.header.last_usable_lba + 34
|
||||
self.totalsectors = self.header.first_usable_lba + self.header.last_usable_lba
|
||||
return True
|
||||
|
||||
def print(self):
|
||||
|
|
|
@ -98,11 +98,11 @@ class sahara(metaclass=LogBase):
|
|||
self.error(str(e))
|
||||
return {}
|
||||
|
||||
def cmd_hello(self, mode, version_min=1, max_cmd_len=0): # CMD 0x1, RSP 0x2
|
||||
def cmd_hello(self, mode, version_min=1, max_cmd_len=0, version=2): # CMD 0x1, RSP 0x2
|
||||
cmd = cmd_t.SAHARA_HELLO_RSP
|
||||
length = 0x30
|
||||
version = SAHARA_VERSION
|
||||
responsedata = pack("<IIIIIIIIIIII", cmd, length, version, version_min, max_cmd_len, mode, 0, 0, 0, 0, 0, 0)
|
||||
#version = SAHARA_VERSION
|
||||
responsedata = pack("<IIIIIIIIIIII", cmd, length, version, version_min, max_cmd_len, mode, 1, 2, 3, 4, 5, 6)
|
||||
try:
|
||||
self.cdc.write(responsedata)
|
||||
return True
|
||||
|
@ -155,8 +155,8 @@ class sahara(metaclass=LogBase):
|
|||
self.error(str(e))
|
||||
return {"mode": "error"}
|
||||
|
||||
def enter_command_mode(self):
|
||||
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_COMMAND):
|
||||
def enter_command_mode(self, version=2):
|
||||
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_COMMAND, version=version):
|
||||
return False
|
||||
res = self.get_rsp()
|
||||
if "cmd" in res:
|
||||
|
@ -179,10 +179,8 @@ class sahara(metaclass=LogBase):
|
|||
|
||||
def cmdexec_get_msm_hwid(self):
|
||||
res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_MSM_HW_ID_READ)
|
||||
try:
|
||||
if res is not None:
|
||||
return int.from_bytes(res[:8],'little')
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
self.debug(str(e))
|
||||
return None
|
||||
|
||||
def cmdexec_get_pkhash(self):
|
||||
|
@ -212,10 +210,11 @@ class sahara(metaclass=LogBase):
|
|||
res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_READ_DEBUG_DATA)
|
||||
return res
|
||||
|
||||
def cmd_info(self):
|
||||
if self.enter_command_mode():
|
||||
def cmd_info(self, version):
|
||||
if self.enter_command_mode(version=version):
|
||||
self.serial = self.cmdexec_get_serial_num()
|
||||
self.serials = "{:08x}".format(self.serial)
|
||||
if version < 3:
|
||||
self.hwid = self.cmdexec_get_msm_hwid()
|
||||
self.pkhash = self.cmdexec_get_pkhash()
|
||||
# if self.version>=2.4:
|
||||
|
@ -234,7 +233,7 @@ class sahara(metaclass=LogBase):
|
|||
cpustr = "Unknown CPU, please send log as issue to https://github.com/bkerler/edl\n"
|
||||
"""
|
||||
if self.version >= 2.4:
|
||||
self.info(f"\n------------------------\n" +
|
||||
self.info(f"\nVersion {hex(version)}\n------------------------\n" +
|
||||
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
|
||||
f"OEM_ID:0x{self.oem_str}," +
|
||||
f"MODEL_ID:0x{self.model_id})\n" +
|
||||
|
@ -243,7 +242,7 @@ class sahara(metaclass=LogBase):
|
|||
f"SBL Version: 0x{self.sblversion}\n")
|
||||
else:
|
||||
"""
|
||||
self.info(f"\n------------------------\n" +
|
||||
self.info(f"\nVersion {hex(version)}\n------------------------\n" +
|
||||
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
|
||||
f"OEM_ID:0x{self.oem_str}," +
|
||||
f"MODEL_ID:0x{self.model_id})\n" +
|
||||
|
@ -307,9 +306,15 @@ class sahara(metaclass=LogBase):
|
|||
else:
|
||||
self.error(f"Couldn't find a suitable loader :(")
|
||||
return False
|
||||
|
||||
else:
|
||||
self.info(f"\nVersion {hex(version)}\n------------------------\n" +
|
||||
f"Serial: 0x{self.serials}\n")
|
||||
if self.programmer=="":
|
||||
self.error("No autodetection of loader possible with sahara version 3 and above :( Aborting.")
|
||||
return False
|
||||
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def streaminginfo(self):
|
||||
|
@ -432,8 +437,8 @@ class sahara(metaclass=LogBase):
|
|||
self.cmd_reset()
|
||||
return True
|
||||
|
||||
def debug_mode(self, dump_partitions=None):
|
||||
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_MEMORY_DEBUG):
|
||||
def debug_mode(self, dump_partitions=None, version=2):
|
||||
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_MEMORY_DEBUG, version=version):
|
||||
return False
|
||||
if os.path.exists("memory"):
|
||||
rmrf("memory")
|
||||
|
@ -501,7 +506,7 @@ class sahara(metaclass=LogBase):
|
|||
return False
|
||||
return False
|
||||
|
||||
def upload_loader(self):
|
||||
def upload_loader(self, version):
|
||||
if self.programmer == "":
|
||||
return ""
|
||||
try:
|
||||
|
@ -512,7 +517,7 @@ class sahara(metaclass=LogBase):
|
|||
self.error(str(e))
|
||||
sys.exit()
|
||||
|
||||
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_IMAGE_TX_PENDING):
|
||||
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_IMAGE_TX_PENDING, version=version):
|
||||
return ""
|
||||
|
||||
try:
|
||||
|
|
|
@ -108,7 +108,53 @@ def extract_hdr(memsection, version, sign_info, mem_section, code_size, signatur
|
|||
len2 = unpack(">H", mem_section[casignature2offset + 2:casignature2offset + 4])[0] + 4
|
||||
rootsignature3offset = casignature2offset + len2
|
||||
len3 = unpack(">H", mem_section[rootsignature3offset + 2:rootsignature3offset + 4])[0] + 4
|
||||
sign_info.pk_hash = hashlib.sha384(mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
|
||||
|
||||
idx = signatureoffset
|
||||
signature = {}
|
||||
while idx != -1:
|
||||
if idx >= len(mem_section):
|
||||
break
|
||||
idx = mem_section.find('\x04\x0B'.encode(), idx)
|
||||
if idx == -1:
|
||||
break
|
||||
length = mem_section[idx + 3]
|
||||
if length > 60:
|
||||
idx += 1
|
||||
continue
|
||||
try:
|
||||
text = mem_section[idx + 4:idx + 4 + length].decode().split(' ')
|
||||
signature[text[2]] = text[1]
|
||||
except:
|
||||
text = ""
|
||||
idx += 1
|
||||
idx = mem_section.find('QC_IMAGE_VERSION_STRING='.encode(), 0)
|
||||
if idx != -1:
|
||||
sign_info.qc_version = grabtext(mem_section[idx + len("QC_IMAGE_VERSION_STRING="):])
|
||||
idx = mem_section.find('OEM_IMAGE_VERSION_STRING='.encode(), 0)
|
||||
if idx != -1:
|
||||
sign_info.oem_version = grabtext(mem_section[idx + len("OEM_IMAGE_VERSION_STRING="):])
|
||||
idx = mem_section.find('IMAGE_VARIANT_STRING='.encode(), 0)
|
||||
if idx != -1:
|
||||
sign_info.image_variant = grabtext(mem_section[idx + len("IMAGE_VARIANT_STRING="):])
|
||||
if "MODEL_ID" in signature:
|
||||
sign_info.model_id = signature["MODEL_ID"]
|
||||
if "OEM_ID" in signature:
|
||||
sign_info.oem_id = signature["OEM_ID"]
|
||||
if "HW_ID" in signature:
|
||||
sign_info.hw_id = signature["HW_ID"]
|
||||
if "SW_ID" in signature:
|
||||
sign_info.sw_id = signature["SW_ID"]
|
||||
if "SW_SIZE" in signature:
|
||||
sign_info.sw_size = signature["SW_SIZE"]
|
||||
if "SHA256" in signature:
|
||||
sign_info.pk_hash = hashlib.sha256(mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
|
||||
elif "SHA384" in signature:
|
||||
sign_info.pk_hash = hashlib.sha384(
|
||||
mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
|
||||
else:
|
||||
sign_info.pk_hash = hashlib.sha384(
|
||||
mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
|
||||
|
||||
except:
|
||||
return None
|
||||
return sign_info
|
||||
|
@ -166,12 +212,24 @@ def extract_old_hdr(signatureoffset, sign_info, mem_section, code_size, signatur
|
|||
sign_info.sw_id = signature["SW_ID"]
|
||||
if "SW_SIZE" in signature:
|
||||
sign_info.sw_size = signature["SW_SIZE"]
|
||||
if "SHA256" in signature:
|
||||
sign_info.pk_hash = hashlib.sha256(mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
|
||||
elif "SHA384" in signature:
|
||||
sign_info.pk_hash = hashlib.sha384(
|
||||
mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
|
||||
return sign_info
|
||||
|
||||
|
||||
def init_loader_db():
|
||||
loaderdb = {}
|
||||
for (dirpath, dirnames, filenames) in os.walk(os.path.join(current_dir,"..","..","Loaders")):
|
||||
loaders=os.path.join(current_dir,"..","..","Loaders")
|
||||
if not os.path.exists(loaders):
|
||||
loaders = os.path.join(current_dir, "Loaders")
|
||||
if not os.path.exists(loaders):
|
||||
print("Couldn't find Loaders directory")
|
||||
return loaderdb
|
||||
|
||||
for (dirpath, dirnames, filenames) in os.walk(loaders):
|
||||
for filename in filenames:
|
||||
file_name = os.path.join(dirpath, filename)
|
||||
found = False
|
||||
|
@ -315,6 +373,7 @@ def main(argv):
|
|||
print("%s has no signature." % filename)
|
||||
copyfile(filename,
|
||||
os.path.join(outputdir, "Unknown", filename[filename.rfind("/") + 1:].lower()))
|
||||
elfpos += 0x30
|
||||
continue
|
||||
if version < 6: # MSM,MDM
|
||||
signatureoffset = memsection.file_start_addr + 0x28 + code_size + signature_size
|
||||
|
|
2
setup.py
2
setup.py
|
@ -4,7 +4,7 @@ import os
|
|||
|
||||
setup(
|
||||
name='edlclient',
|
||||
version='3.60',
|
||||
version='3.62',
|
||||
packages=find_packages(),
|
||||
long_description=open("README.md").read(),
|
||||
scripts=['edl','edlclient/Tools/qc_diag.py','edlclient/Tools/sierrakeygen.py','edlclient/Tools/boottodwnload','edlclient/Tools/enableadb','edlclient/Tools/fhloaderparse','edlclient/Tools/beagle_to_loader'],
|
||||
|
|
Loading…
Reference in a new issue