Merge pull request #558 from ColdWindScholar/master

More Beautiful and bug fixes
This commit is contained in:
Bjoern Kerler 2024-06-13 23:59:29 +02:00 committed by GitHub
commit a6bb478da0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 653 additions and 612 deletions

View file

@ -1,7 +1,8 @@
import socket
from binascii import hexlify
class tcpclient():
class tcpclient:
def __init__(self, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ("localhost", port)
@ -13,7 +14,7 @@ class tcpclient():
for command in commands:
self.sock.sendall(bytes(command, 'utf-8'))
data = ""
while not "<ACK>" in data and not "<NAK>" in data:
while "<ACK>" not in data and "<NAK>" not in data:
tmp = self.sock.recv(4096)
if tmp == b"":
continue
@ -25,5 +26,3 @@ class tcpclient():
finally:
print("closing socket")
self.sock.close()

View file

@ -1,7 +1,8 @@
#!/usr/bin/env python3
from edl.Library.tcpclient import tcpclient
class client():
class client:
def __init__(self):
self.commands = []
@ -18,6 +19,7 @@ class client():
def memcpy(self, dest, src, size):
self.commands.append(f"memcpy:{hex(dest)},{hex(src)},{hex(size)}")
def main():
exp = client()
exp.commands = [
@ -29,5 +31,6 @@ def main():
]
exp.send()
if __name__ == "__main__":
main()

32
edl
View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -127,34 +127,36 @@ Options:
--resetmode=mode Resetmode for reset (poweroff, reset, edl, etc.)
"""
import logging
import os
import re
import subprocess
import sys
import time
import logging
import subprocess
import re
from docopt import docopt
from edlclient.Config.usb_ids import default_ids
from edlclient.Library.utils import LogBase
from edlclient.Library.Connection.usblib import usb_class
from edlclient.Library.Connection.seriallib import serial_class
from edlclient.Library.sahara import sahara
from edlclient.Library.streaming_client import streaming_client
from edlclient.Library.Connection.usblib import usb_class
from edlclient.Library.firehose_client import firehose_client
from edlclient.Library.streaming import Streaming
from edlclient.Library.sahara import sahara
from edlclient.Library.sahara_defs import cmd_t, sahara_mode_t
from edlclient.Library.streaming import Streaming
from edlclient.Library.streaming_client import streaming_client
from edlclient.Library.utils import LogBase
from edlclient.Library.utils import is_windows
from binascii import hexlify
args = docopt(__doc__, version='3')
print("Qualcomm Sahara / Firehose Client V3.62 (c) B.Kerler 2018-2023.")
print("Qualcomm Sahara / Firehose Client V3.62 (c) B.Kerler 2018-2024.")
def parse_cmd(rargs):
cmds = ["server", "printgpt", "gpt", "r", "rl", "rf", "rs", "w", "wl", "wf", "ws", "e", "es", "ep", "footer",
"peek", "peekhex", "peekdword", "peekqword", "memtbl", "poke", "pokehex", "pokedword", "pokeqword",
"memcpy", "secureboot", "pbl", "qfp", "getstorageinfo", "setbootablestoragedrive", "getactiveslot", "setactiveslot",
"memcpy", "secureboot", "pbl", "qfp", "getstorageinfo", "setbootablestoragedrive", "getactiveslot",
"setactiveslot",
"send", "xml", "rawxml", "reset", "nop", "modules", "memorydump", "provision", "qfil"]
for cmd in cmds:
if rargs[cmd]:
@ -239,7 +241,6 @@ class main(metaclass=LogBase):
if re.findall(r'QCUSB', str(proper_driver)):
self.warning(f'Please first install libusb_win32 driver from Zadig')
mode = ""
loop = 0
vid = int(args["--vid"], 16)
pid = int(args["--pid"], 16)
@ -285,14 +286,13 @@ class main(metaclass=LogBase):
self.sahara.programmer = loader
self.info("Waiting for the device")
resp = None
self.cdc.timeout = 1500
conninfo = self.doconnect(loop)
mode = conninfo["mode"]
if not "data" in conninfo:
if conninfo.get("data"):
version = 2
else:
version = conninfo["data"].version
version = conninfo.get("data").version
if mode == "sahara":
cmd = conninfo["cmd"]
if cmd == cmd_t.SAHARA_HELLO_REQ:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,20 +1,20 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 serial
import serial.tools.list_ports
import inspect
import traceback
from binascii import hexlify
try:
from edlclient.Library.utils import *
except:
from Library.utils import *
class DeviceClass(metaclass=LogBase):
def __init__(self, loglevel=logging.INFO, portconfig=None, devclass=-1):
@ -119,7 +119,7 @@ class DeviceClass(metaclass=LogBase):
stack_trace = traceback.format_stack(frame)
td = []
for trace in stack_trace:
if not "verify_data" in trace and not "Port" in trace:
if "verify_data" not in trace and "Port" not in trace:
td.append(trace)
self.debug(td[:-1])

View file

@ -1,13 +1,12 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 os.path
import time
import sys
if not sys.platform.startswith('win32'):
import termios
@ -15,15 +14,16 @@ if not sys.platform.startswith('win32'):
def _reset_input_buffer():
return
def _reset_input_buffer_org(self):
if not sys.platform.startswith('win32'):
return termios.tcflush(self.fd, termios.TCIFLUSH)
import serial
import serial.tools.list_ports
import inspect
import traceback
from binascii import hexlify
try:
from edlclient.Library.utils import *
from edlclient.Library.Connection.devicehandler import DeviceClass
@ -94,7 +94,6 @@ class serial_class(DeviceClass):
self.device.setDTR(DTR)
self.debug("Linecoding set")
def write(self, command, pktsize=None):
if pktsize is None:
pktsize = 512
@ -173,7 +172,7 @@ class serial_class(DeviceClass):
bytestoread = resplen - len(info)
extend(info)
if b"<?xml " in info:
while not b"response " in res or res[-7:]!=b"</data>":
while b"response " not in res or res[-7:] != b"</data>":
extend(epr(1))
return res
bytestoread = resplen
@ -218,5 +217,3 @@ class serial_class(DeviceClass):
self.device.flush()
res = self.usbread(resplen)
return res

View file

@ -1,30 +1,29 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 io
import logging
import usb.core # pyusb
import usb.util
import time
import inspect
import array
import usb.backend.libusb0
from enum import Enum
import inspect
import logging
from binascii import hexlify
from ctypes import c_void_p, c_int
from enum import Enum
import usb.backend.libusb0
import usb.core # pyusb
import usb.util
try:
from edlclient.Library.utils import *
except:
from Library.utils import *
if not is_windows():
import usb.backend.libusb1
from struct import pack, calcsize
import traceback
from struct import pack
try:
from edlclient.Library.Connection.devicehandler import DeviceClass
except:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -36,6 +36,7 @@ except ImportError as e:
nothing = None
pass
class modules(metaclass=LogBase):
def __init__(self, fh, serial: int, supported_functions, loglevel, devicemodel: str, args):
self.fh = fh

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -33,8 +33,9 @@ class nothing(metaclass=LogBase):
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')
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):
"""

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -25,6 +25,7 @@ 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 +129,8 @@ deviceconfig = {
class oneplus(metaclass=LogBase):
def __init__(self, fh, projid:str="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
@ -573,11 +575,11 @@ def main():
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>\"")
print('./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)
print(
f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setswprojmodel " +
'./edl.py rawxml "<?xml version=\\"1.0\\" ?><data><setswprojmodel ' +
f"token=\\\"{token}\\\" pk=\\\"{pk}\\\" /></data>\" --debugmode")
elif args["setprojmodel_verify"]:
projid = args["--projid"][0]
@ -616,8 +618,7 @@ def main():
def test_setswprojmodel_verify():
deviceresp = b"RX:<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\nRX:<data>\nRX:<response value=\"ACK\" " + \
b"device_timestamp=\"2507003650\" /></data>\n<?xmlversion=\"1.0\" ? ><data><setprocstart /></data>"
deviceresp = b'RX:<?xml version="1.0" encoding="UTF-8" ?>\nRX:<data>\nRX:<response value="ACK" device_timestamp="2507003650" /></data>\n<?xmlversion="1.0" ? ><data><setprocstart /></data>'
projid = "20889"
op = oneplus(None, projid=projid, serial=123456)
data = deviceresp.decode('utf-8')

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -109,7 +109,7 @@ class sid(Enum):
'''
class paramtools():
class paramtools:
paramitems = {
sid.PARAM_SID_PRODUCT.value[0]: {
0x18: ["8c", "project_name"],
@ -375,7 +375,7 @@ class paramtools():
def parse_encrypted(self, rdata, sid):
data = rdata[(sid * 0x400):(sid * 0x400) + 0x1000]
itemdata, hv, cv, updatecounter = self.decryptsid(data)
if itemdata != None:
if itemdata is not None:
itemdata = bytearray(itemdata)
print(
f"Offset {hex(sid * 0x400)}: hv {hex(hv)}, cv {hex(cv)}, increase_enc_update_counter {hex(updatecounter)}.")
@ -420,7 +420,7 @@ class paramtools():
itemlength = 0x400
itemdata = rdata[pos + 0x18:pos + 0x18 + itemlength]
i = 0
while (i < len(itemdata) - 0x22):
while i < len(itemdata) - 0x22:
sidindex = (pos // 0x400) & 0x1FF
offset = i + 0x18
# if sidindex==0x334 and offset==0x80:
@ -439,7 +439,7 @@ class paramtools():
length = self.parse_data(i, itemdata, offset, param, sidindex)
i += length
if length > 4:
if (length % 4):
if length % 4:
i += 4 - (length % 4)
def parse_data(self, i, itemdata, offset, param, sidindex, encrypted=False):

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -425,7 +425,7 @@ class cryptutils:
return q
def pss_verify(self, e, N, msghash, signature, emBits=1024, salt=None):
if salt == None:
if salt is None:
slen = self.digestLen
else:
slen = len(salt)
@ -469,20 +469,14 @@ class cryptutils:
if salt is not None:
inBlock = b"\x00" * 8 + msghash + salt
mhash = self.hash(inBlock)
if mhash == mhash:
return True
else:
return False
return mhash == mhash
else:
salt = TS[-self.digestLen:]
inBlock = b"\x00" * 8 + msghash + salt
mhash = self.hash(inBlock)
if mhash == mhash:
return True
else:
return False
return mhash == mhash
class hash():
class hash:
def __init__(self, hashtype="SHA256"):
if hashtype == "SHA1":
self.hash = self.sha1

View file

@ -1,33 +1,28 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 binascii
import io
import json
import os.path
import platform
import time
import json
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, AB_FLAG_OFFSET, AB_PARTITION_ATTR_SLOT_ACTIVE, MAX_PRIORITY, PART_ATT_PRIORITY_BIT
from edlclient.Library.gpt import PART_ATT_PRIORITY_VAL, PART_ATT_ACTIVE_VAL, PART_ATT_MAX_RETRY_COUNT_VAL, PART_ATT_SUCCESSFUL_VAL, PART_ATT_UNBOOTABLE_VAL
from edlclient.Library.gpt import gpt, AB_FLAG_OFFSET, AB_PARTITION_ATTR_SLOT_ACTIVE
from edlclient.Library.sparse import QCSparse
from edlclient.Library.utils import *
from edlclient.Library.utils import progress
from queue import Queue
from threading import Thread
rq = Queue()
def writedata(filename, rq):
pos = 0
with open(filename, "wb") as wf:
@ -146,11 +141,10 @@ def writefile(wf, q, stop):
break
class asyncwriter():
class asyncwriter:
def __init__(self, wf):
self.writequeue = Queue()
self.worker = Thread(target=writefile, args=(wf, self.writequeue, lambda: self.stopthreads,))
self.worker.setDaemon(True)
self.worker = Thread(target=writefile, args=(wf, self.writequeue, lambda: self.stopthreads,), daemon=True)
self.stopthreads = False
self.worker.start()
@ -231,7 +225,8 @@ class firehose(metaclass=LogBase):
break
else:
if partitionname in guid_gpt.partentries:
return [True, lun, data, guid_gpt] if send_full else [True, lun, guid_gpt.partentries[partitionname]]
return [True, lun, data, guid_gpt] if send_full else [True, lun,
guid_gpt.partentries[partitionname]]
for part in guid_gpt.partentries:
fpartitions[lunname].append(part)
return [False, fpartitions]
@ -333,7 +328,7 @@ class firehose(metaclass=LogBase):
def cmd_reset(self, mode="reset"):
if mode is None:
mode = "reset"
data = "<?xml version=\"1.0\" ?><data><power value=\"" + mode + "\"/></data>"
data = f'<?xml version="1.0" ?><data><power value="{mode}"/></data>'
val = self.xmlsend(data)
try:
v = None
@ -366,7 +361,7 @@ class firehose(metaclass=LogBase):
return val.error
def cmd_nop(self):
data = "<?xml version=\"1.0\" ?><data><nop /></data>"
data = '<?xml version="1.0" ?><data><nop /></data>'
resp = self.xmlsend(data, True)
self.debug(resp.data.hex())
info = b""
@ -1246,7 +1241,7 @@ class firehose(metaclass=LogBase):
if len(imei) != 16:
self.info("IMEI must be 16 digits")
return False
data = "<?xml version=\"1.0\" ?><data><writeIMEI len=\"16\"/></data>"
data = '<?xml version="1.0" ?><data><writeIMEI len="16"/></data>'
val = self.xmlsend(data)
if val.resp:
self.info("writeIMEI succeeded.")
@ -1256,7 +1251,7 @@ class firehose(metaclass=LogBase):
return False
def cmd_getstorageinfo(self):
data = "<?xml version=\"1.0\" ?><data><getstorageinfo physical_partition_number=\"0\"/></data>"
data = '<?xml version="1.0" ?><data><getstorageinfo physical_partition_number="0"/></data>'
val = self.xmlsend(data)
if val.data == '' and val.log == '' and val.resp:
return None
@ -1271,7 +1266,7 @@ class firehose(metaclass=LogBase):
if len(v) > 1:
res[v[0]] = v[1]
else:
if "\"storage_info\"" in value:
if '"storage_info"' in value:
try:
info = value.replace("INFO:", "")
si = json.loads(info)["storage_info"]
@ -1330,14 +1325,17 @@ class firehose(metaclass=LogBase):
new_flags &= ~(AB_PARTITION_ATTR_SLOT_ACTIVE << (AB_FLAG_OFFSET * 8))
return new_flags
def patch_helper(gpt_data_a, gpt_data_b, guid_gpt_a, guid_gpt_b, partition_a, partition_b, slot_a_status, slot_b_status, is_boot):
def patch_helper(gpt_data_a, gpt_data_b, guid_gpt_a, guid_gpt_b, partition_a, partition_b, slot_a_status,
slot_b_status, is_boot):
part_entry_size = guid_gpt_a.header.part_entry_size
rf_a = BytesIO(gpt_data_a)
rf_b = BytesIO(gpt_data_b)
entryoffset_a = partition_a.entryoffset - ((guid_gpt_a.header.part_entry_start_lba - 2) * guid_gpt_a.sectorsize)
entryoffset_b = partition_b.entryoffset - ((guid_gpt_b.header.part_entry_start_lba - 2) * guid_gpt_b.sectorsize)
entryoffset_a = partition_a.entryoffset - (
(guid_gpt_a.header.part_entry_start_lba - 2) * guid_gpt_a.sectorsize)
entryoffset_b = partition_b.entryoffset - (
(guid_gpt_b.header.part_entry_start_lba - 2) * guid_gpt_b.sectorsize)
rf_a.seek(entryoffset_a)
rf_b.seek(entryoffset_b)
@ -1423,7 +1421,8 @@ class firehose(metaclass=LogBase):
prim_corrupted = prim_hdr_crc != test_hdr_crc or prim_part_table_crc != test_part_table_crc
backup_hdr = backup_gpt_data[headeroffset: headeroffset + backup_guid_gpt.header.header_size]
test_hdr = backup_guid_gpt.fix_gpt_crc(backup_gpt_data)[headeroffset : headeroffset + backup_guid_gpt.header.header_size]
test_hdr = backup_guid_gpt.fix_gpt_crc(backup_gpt_data)[
headeroffset: headeroffset + backup_guid_gpt.header.header_size]
backup_hdr_crc, test_hdr_crc = backup_hdr[0x10: 0x10 + 4], test_hdr[0x10: 0x10 + 4]
backup_part_table_crc, test_part_table_crc = backup_hdr[0x58: 0x58 + 4], test_hdr[0x58: 0x58 + 4]
backup_corrupted = backup_hdr_crc != test_hdr_crc or backup_part_table_crc != test_part_table_crc
@ -1464,7 +1463,8 @@ class firehose(metaclass=LogBase):
slot = partitionname_a.lower()[-2:]
partition_a = backup_guid_gpt_a.partentries[partitionname_a]
if slot == "_a":
active_a = ((partition_a.flags >> (AB_FLAG_OFFSET*8))&0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
active_a = ((partition_a.flags >> (
AB_FLAG_OFFSET * 8)) & 0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
if (active_a and slot_a_status) or (not active_a and slot_b_status):
return True
@ -1483,14 +1483,22 @@ class firehose(metaclass=LogBase):
self.error(f"Cannot find partition {partitionname_b}")
return False
_, lun_b, gpt_data_b, guid_gpt_b = resp
backup_gpt_data_b, backup_guid_gpt_b = self.get_gpt(lun_b, 0, 0 , 0, guid_gpt_b.header.backup_lba)
backup_gpt_data_b, backup_guid_gpt_b = self.get_gpt(lun_b, 0, 0, 0,
guid_gpt_b.header.backup_lba)
if not check_gpt_hdr and partitionname_a[:3] != "xbl": # xbl partition don't need check consistency
sts, gpt_data_a, backup_gpt_data_a = ensure_gpt_hdr_consistency(guid_gpt_a, backup_guid_gpt_a, gpt_data_a, backup_gpt_data_a)
if not check_gpt_hdr and partitionname_a[
:3] != "xbl": # xbl partition don't need check consistency
sts, gpt_data_a, backup_gpt_data_a = ensure_gpt_hdr_consistency(guid_gpt_a,
backup_guid_gpt_a,
gpt_data_a,
backup_gpt_data_a)
if not sts:
return False
if lun_a != lun_b:
sts, gpt_data_b, backup_gpt_data_b = ensure_gpt_hdr_consistency(guid_gpt_b, backup_guid_gpt_b, gpt_data_b, backup_gpt_data_b)
sts, gpt_data_b, backup_gpt_data_b = ensure_gpt_hdr_consistency(guid_gpt_b,
backup_guid_gpt_b,
gpt_data_b,
backup_gpt_data_b)
if not sts:
return False
check_gpt_hdr = True
@ -1513,12 +1521,10 @@ class firehose(metaclass=LogBase):
return False
return True
def cmd_test(self, cmd):
token = "1234"
pk = "1234"
data = "<?xml version=\"1.0\" ?>\n<data>\n<" + cmd + " token=\"" + token + "\" pk=\"" + pk + "\" />\n</data>"
data = f'<?xml version="1.0" ?>\n<data>\n<{cmd} token="{token}" pk="{pk}" />\n</data>'
val = self.xmlsend(data)
if val.resp:
if b"raw hex token" in val[2]:
@ -1528,7 +1534,7 @@ class firehose(metaclass=LogBase):
return False
def cmd_getstorageinfo_string(self):
data = "<?xml version=\"1.0\" ?><data><getstorageinfo /></data>"
data = '<?xml version="1.0" ?><data><getstorageinfo /></data>'
val = self.xmlsend(data)
if val.resp:
self.info(f"GetStorageInfo:\n--------------------\n")

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -649,7 +649,8 @@ class firehose_client(metaclass=LogBase):
prim_guid_gpt = res[3]
_, backup_guid_gpt = self.firehose.get_gpt(lun, 0, 0, 0, prim_guid_gpt.header.backup_lba)
partition = backup_guid_gpt.partentries["boot_a"]
active = ((partition.flags >> (AB_FLAG_OFFSET*8))&0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
active = ((partition.flags >> (
AB_FLAG_OFFSET * 8)) & 0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
if active:
self.printer("Current active slot: a")
return True
@ -659,7 +660,8 @@ class firehose_client(metaclass=LogBase):
prim_guid_gpt = res[3]
_, backup_guid_gpt = self.firehose.get_gpt(lun, 0, 0, 0, prim_guid_gpt.header.backup_lba)
partition = backup_guid_gpt.partentries["boot_b"]
active = ((partition.flags >> (AB_FLAG_OFFSET*8))&0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
active = ((partition.flags >> (
AB_FLAG_OFFSET * 8)) & 0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
if active:
self.printer("Current active slot: b")
return True
@ -762,7 +764,8 @@ class firehose_client(metaclass=LogBase):
int(options["--gpt-part-entry-size"]),
int(options["--gpt-part-entry-start-lba"]))
if guid_gpt is None:
self.error("Error: Can not fetch GPT table from device, you may need to use `edl w gpt` to write a partition table first.`")
self.error(
"Error: Can not fetch GPT table from device, you may need to use `edl w gpt` to write a partition table first.`")
break
for filename in filenames:
partname = os.path.basename(filename)

View file

@ -1,22 +1,23 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 os
import sys
import argparse
import colorama
import copy
import logging
import logging.config
from enum import Enum
from binascii import hexlify
from struct import calcsize, unpack, pack
from io import BytesIO
import os
import sys
from binascii import crc32
from binascii import hexlify
from enum import Enum
from struct import calcsize, unpack, pack
import colorama
class ColorFormatter(logging.Formatter):
LOG_COLORS = {
@ -193,7 +194,6 @@ AB_SLOT_INACTIVE_VAL = 0x0
AB_SLOT_ACTIVE = 1
AB_SLOT_INACTIVE = 0
PART_ATT_PRIORITY_BIT = 48
PART_ATT_ACTIVE_BIT = 50
PART_ATT_MAX_RETRY_CNT_BIT = 51
@ -349,7 +349,6 @@ class gpt(metaclass=LogBase):
def parseheader(self, gptdata, sectorsize=512):
return self.gpt_header(gptdata[sectorsize:sectorsize + 0x5C])
def parse(self, gptdata, sectorsize=512):
self.header = self.gpt_header(gptdata[sectorsize:sectorsize + 0x5C])
self.sectorsize = sectorsize
@ -414,7 +413,8 @@ class gpt(metaclass=LogBase):
mstr = "\nGPT Table:\n-------------\n"
for partitionname in self.partentries:
partition = self.partentries[partitionname]
active = ((partition.flags >> (AB_FLAG_OFFSET*8))&0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
active = ((partition.flags >> (
AB_FLAG_OFFSET * 8)) & 0xFF) & AB_PARTITION_ATTR_SLOT_ACTIVE == AB_PARTITION_ATTR_SLOT_ACTIVE
mstr += ("{:20} Offset 0x{:016x}, Length 0x{:016x}, Flags 0x{:016x}, UUID {}, Type {}, Active {}\n".format(
partition.name + ":", partition.sector * self.sectorsize, partition.sectors * self.sectorsize,
partition.flags, partition.unique, partition.type, active))

View file

@ -1,15 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 logging
from binascii import hexlify
from struct import unpack
import time
from struct import unpack
MAX_PACKET_LEN = 4096

View file

@ -1,17 +1,15 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 binascii
import time
import inspect
import logging
import os
import sys
import logging
import inspect
from struct import unpack, pack
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)
@ -22,6 +20,7 @@ except:
from Library.utils import read_object, print_progress, rmrf, LogBase
from Config.qualcomm_config import sochw, msmids, root_cert_hash
class loader_utils(metaclass=LogBase):
def __init__(self, loglevel=logging.INFO):
self.__logger = self.__logger
@ -88,4 +87,3 @@ class loader_utils(metaclass=LogBase):
rmsmid = '0' + rmsmid
msmiddb.append(rmsmid)
return msmiddb

View file

@ -1,16 +1,16 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 os
import pt64
import pt
import argparse
import pt
import pt64
def pt64_walk(data, ttbr, tnsz, levels=3):
print("Dumping page tables (levels=%d)" % levels)
@ -50,7 +50,7 @@ def pt32_walk(data, ttbr, skip):
i += 1
if i <= skip:
continue
if type(fl) == pt.pt_desc:
if isinstance(fl, pt.pt_desc):
print("")
print("Second level (va = %08x)" % va)
print("---------------------------------------------")

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -87,6 +87,7 @@ def get_fld(mfld, level):
return table_entry4k(mfld, level)
return None
class descriptor(object):
def get_name(self):
pass

View file

@ -1,25 +1,26 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 binascii
import time
import inspect
import logging
import os
import sys
import logging
import inspect
import time
from struct import pack
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)
from edlclient.Library.utils import read_object, print_progress, rmrf, LogBase
from edlclient.Config.qualcomm_config import sochw, msmids, root_cert_hash
from edlclient.Library.utils import print_progress, rmrf, LogBase
from edlclient.Config.qualcomm_config import msmids, root_cert_hash
from edlclient.Library.loader_db import loader_utils
from edlclient.Library.sahara_defs import ErrorDesc, cmd_t, exec_cmd_t, sahara_mode_t, status_t, \
CommandHandler, SAHARA_VERSION
CommandHandler
class sahara(metaclass=LogBase):
def __init__(self, cdc, loglevel):
@ -347,7 +348,6 @@ class sahara(metaclass=LogBase):
self.cdc.write(pack("<II", cmd_t.SAHARA_RESET_STATE_MACHINE_ID, 0x8))
return True
def cmd_reset(self):
self.cdc.write(pack("<II", cmd_t.SAHARA_RESET_REQ, 0x8))
try:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -12,9 +12,11 @@ from io import BytesIO
SAHARA_VERSION = 2
SAHARA_MIN_VERSION = 1
class DataError(Exception):
pass
class cmd_t:
SAHARA_HELLO_REQ = 0x1
SAHARA_HELLO_RSP = 0x2
@ -36,6 +38,7 @@ class cmd_t:
SAHARA_64BIT_MEMORY_READ_DATA = 0x12
SAHARA_RESET_STATE_MACHINE_ID = 0x13
class cmd_t_version:
SAHARA_HELLO_REQ = 0x1
SAHARA_HELLO_RSP = 1
@ -57,6 +60,7 @@ class cmd_t_version:
SAHARA_64BIT_MEMORY_READ_DATA = 2
SAHARA_RESET_STATE_MACHINE_ID = 2
class exec_cmd_t:
SAHARA_EXEC_CMD_NOP = 0x00
SAHARA_EXEC_CMD_SERIAL_NUM_READ = 0x01
@ -69,6 +73,7 @@ class exec_cmd_t:
SAHARA_EXEC_CMD_GET_COMMAND_ID_LIST = 0x08
SAHARA_EXEC_CMD_GET_TRAINING_DATA = 0x09
class sahara_mode_t:
SAHARA_MODE_IMAGE_TX_PENDING = 0x0
SAHARA_MODE_IMAGE_TX_COMPLETE = 0x1

View file

@ -1,23 +1,22 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 inspect
import logging
import sys
import os
import sys
import inspect
from queue import Queue
from struct import unpack
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)
from edlclient.Library.utils import LogBase, print_progress
MAX_STORE_SIZE = 1024 * 1024 * 1024 * 2 # 2 GBs

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -43,6 +43,7 @@ class open_multi_mode_type:
OPEN_MULTI_MODE_EMMC_GPP3 = 0x27 # EMMC GPP partition 3
OPEN_MULTI_MODE_EMMC_GPP4 = 0x28 # EMMC GPP partition 4
class response_code_type:
ACK = 0x00 # Successful
RESERVED_1 = 0x01 # Reserved

View file

@ -1,24 +1,25 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 sys
import codecs
import copy
import datetime as dt
import logging
import logging.config
import codecs
import struct
import os
import shutil
import stat
import colorama
import copy
import datetime as dt
import struct
import sys
import time
from io import BytesIO
from struct import unpack, pack
from struct import unpack
import colorama
try:
from capstone import *
@ -29,11 +30,13 @@ try:
except ImportError:
print("Keystone library is missing (optional).")
def is_windows():
if sys.platform == 'win32' or sys.platform == 'win64' or sys.platform == 'winnt':
return True
return False
class structhelper_io:
pos = 0
@ -83,6 +86,7 @@ class structhelper_io:
def seek(self, pos):
self.data.seek(pos)
def find_binary(data, strf, pos=0):
t = strf.split(b".")
pre = 0
@ -113,6 +117,7 @@ def find_binary(data, strf, pos=0):
pre += 1
return None
class progress:
def __init__(self, pagesize):
self.progtime = 0
@ -124,7 +129,7 @@ class progress:
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)
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
@ -188,6 +193,7 @@ class progress:
self.progpos = pos
self.progtime = t0
class structhelper:
pos = 0
@ -248,6 +254,7 @@ class structhelper:
def seek(self, pos):
self.pos = pos
def do_tcp_server(client, arguments, handler):
def tcpprint(arg):
if isinstance(arg, bytes) or isinstance(arg, bytearray):
@ -575,7 +582,7 @@ class patchtools:
badchars = self.has_bad_uart_chars(data)
if not badchars:
badchars = self.has_bad_uart_chars(data2)
if not (badchars):
if not badchars:
return div
div += 4
@ -685,7 +692,7 @@ class patchtools:
continue
rt += 1
prep = data[rt:].find(t[i])
if (prep != 0):
if prep != 0:
error = 1
break
rt += len(t[i])
@ -699,7 +706,7 @@ class patchtools:
return None
def read_object(data: object, definition: object) -> object:
def read_object(data: object, definition: object) -> dict:
"""
Unpacks a structure using the given data and definition.
"""

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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

View file

@ -1,15 +1,16 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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. !!!!!
# Beagle to EDL Loader
import os,sys
import sys
from struct import unpack
def main():
if len(sys.argv) < 2:
print("Usage: ./beagle_to_loader.py [beagle_log.bin] [loader.elf]")
@ -45,5 +46,6 @@ def main():
print("Done.")
if __name__ == "__main__":
main()

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -15,6 +15,7 @@ import usb.core
from enum import Enum
import os, sys, inspect
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
sys.path.insert(0, current_dir)
@ -23,6 +24,7 @@ try:
except ImportError as e:
print(current_dir)
from qc_diag import qcdiag
pass
try:
@ -38,9 +40,11 @@ class vendor(Enum):
netgear = 0x0846
telit = 0x413c
class deviceclass:
vid = 0
pid = 0
def __init__(self, vid, pid):
self.vid = vid
self.pid = pid
@ -78,7 +82,8 @@ class connection(metaclass=LogBase):
headers = {'Referer': 'http://192.168.0.1/index.html', 'Accept-Charset': 'UTF-8'}
r = requests.get(url, headers=headers)
if b"FACTORY:ok" in r.content or b"success" in r.content:
print(f"Detected a ZTE in web mode .... switching mode success (convert back by sending \"AT+ZCDRUN=F\" via AT port)")
print(
f"Detected a ZTE in web mode .... switching mode success (convert back by sending \"AT+ZCDRUN=F\" via AT port)")
return self.waitforusb(vendor.zte.value, 0x0016)
return False
@ -202,6 +207,7 @@ class connection(metaclass=LogBase):
data["vendor"] = "Telit"
return data
class dwnloadtools(metaclass=LogBase):
def sendcmd(self, tn, cmd):
tn.write(bytes(cmd, 'utf-8') + b"\n")
@ -264,6 +270,7 @@ class dwnloadtools(metaclass=LogBase):
diag.disconnect()
cn.close()
def main():
version = "1.1"
info = 'Modem Gimme-EDL ' + version + ' (c) B. Kerler 2020-2021'
@ -277,8 +284,12 @@ def main():
help='use logfile for debug log',
default="")
args = parser.parse_args()
if not args.port:
parser.print_help()
return
dw = dwnloadtools()
dw.run(args)
if __name__ == "__main__":
main()

View file

@ -1,17 +1,18 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 argparse
import hashlib
import time
from Exscript.protocols.telnetlib import Telnet
import requests
import serial
import serial.tools.list_ports
import argparse
import requests
import hashlib
from Exscript.protocols.telnetlib import Telnet
try:
from edlclient.Tools.qc_diag import qcdiag
@ -38,8 +39,9 @@ import logging.config
import logging.handlers
import colorama
itoa64 = bytearray(b"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
def _crypt_to64(s, v, n):
out = bytearray()
while --n >= 0:
@ -191,7 +193,8 @@ class connection:
mode = "AT"
break
elif device.pid == 0x1403:
print(f"Detected a {atvendortable[device.vid][0]} device with pid {hex(device.pid)} in Web mode")
print(
f"Detected a {atvendortable[device.vid][0]} device with pid {hex(device.pid)} in Web mode")
mode = "Web"
self.ZTE_Web()
break
@ -386,17 +389,14 @@ class adbtools(metaclass=LogBase):
print("Sending switch command via diag")
res = self.ZTE(cn, enable)
elif info["vendor"] == "Simcom":
res=self.Simcom(cn)
res = self.Simcom(cn, enable)
elif info["vendor"] == "Fibocom":
res = self.Fibocom(cn, enable)
elif info["vendor"] == "Alcatel":
res = self.Alcatel(enable)
elif info["vendor"] == "Samsung":
res = self.Samsung(cn, enable)
if enable:
mode="enabled"
else:
mode="disabled"
mode = "enabled" if enable else "disabled"
if res:
print("ADB successfully " + mode)
else:

View file

@ -1,25 +1,32 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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 inspect
import os
import sys
from os import walk
import hashlib
from struct import unpack, pack
from shutil import copyfile
import os, sys, inspect
from io import BytesIO
from Library.utils import elf
from Library.loader_db import loader_utils
from os import walk
from shutil import copyfile
from struct import unpack
try:
from Config.qualcomm_config import vendor
from Library.loader_db import loader_utils
from Library.utils import elf
except ModuleNotFoundError:
from edlclient.Config.qualcomm_config import vendor
from edlclient.Library.loader_db import loader_utils
from edlclient.Library.utils import elf
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
lu = loader_utils()
class MBN:
def __init__(self, memory):
self.imageid, self.flashpartitionversion, self.imagesrc, self.loadaddr, self.imagesz, self.codesz, \
@ -106,7 +113,8 @@ def extract_hdr(memsection, version, sign_info, mem_section, code_size, signatur
len1 = unpack(">H", mem_section[signatureoffset + 2:signatureoffset + 4])[0] + 4
casignature2offset = signatureoffset + len1
len2 = unpack(">H", mem_section[casignature2offset + 2:casignature2offset + 4])[0] + 4
rootsignature3 = mem_section[(casignature2offset + len2):(casignature2offset + len2) + 999999999].split(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')[0]
rootsignature3 = mem_section[(casignature2offset + len2):(casignature2offset + len2) + 999999999].split(
b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')[0]
idx = signatureoffset
signature = {}
@ -171,7 +179,8 @@ def extract_old_hdr(signatureoffset, sign_info, mem_section, code_size, signatur
len1 = unpack(">H", mem_section[signatureoffset + 2:signatureoffset + 4])[0] + 4
casignature2offset = signatureoffset + len1
len2 = unpack(">H", mem_section[casignature2offset + 2:casignature2offset + 4])[0] + 4
rootsignature3 = mem_section[(casignature2offset + len2):(casignature2offset + len2) + 999999999].split(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')[0]
rootsignature3 = mem_section[(casignature2offset + len2):(casignature2offset + len2) + 999999999].split(
b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')[0]
sign_info.pk_hash = hashlib.sha256(rootsignature3).hexdigest()
idx = signatureoffset
@ -381,7 +390,8 @@ def main(argv):
filelist.append(signinfo)
break
elif version >= 6: # SDM
signinfo = extract_hdr(memsection, version, signinfo, mem_section, code_size, signature_size, hdr1,
signinfo = extract_hdr(memsection, version, signinfo, mem_section, code_size, signature_size,
hdr1,
hdr2, hdr3, hdr4)
if signinfo is None:
continue

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# (c) B.Kerler 2018-2024 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
@ -90,7 +90,7 @@ subnvitem_type = [
]
class fs_factimage_read_info():
class fs_factimage_read_info:
def_fs_factimage_read_info = [
("stream_state", "B"), # 0 indicates no more data to be sent, otherwise set to 1
("info_cluster_sent", "B"), # 0 indicates if info_cluster was not sent, else 1
@ -117,7 +117,7 @@ class fs_factimage_read_info():
return data
class FactoryHeader():
class FactoryHeader:
def_factory_header = [
("magic1", "I"),
("magic2", "I"),
@ -160,7 +160,7 @@ class FactoryHeader():
return data
class nvitem():
class nvitem:
item = 0x0
data = b""
status = 0x0
@ -409,7 +409,7 @@ class qcdiag(metaclass=LogBase):
self.cdc.close(True)
def send(self, cmd):
if self.hdlc != None:
if self.hdlc is not None:
return self.hdlc.send_cmd_np(cmd)
def cmd_info(self):
@ -502,7 +502,7 @@ class qcdiag(metaclass=LogBase):
res, nvitem = self.read_nvitem(item)
if res:
info = self.DecodeNVItems(nvitem)
if res != False:
if res:
if nvitem.name != "":
ItemNumber = f"{hex(item)} ({nvitem.name}): "
else:
@ -520,7 +520,7 @@ class qcdiag(metaclass=LogBase):
def print_nvitemsub(self, item, index):
res, nvitem = self.read_nvitemsub(item, index)
info = self.DecodeNVItems(nvitem)
if res != False:
if res:
if nvitem.name != "":
ItemNumber = f"{hex(item), hex(index)} ({nvitem.name}): "
else:
@ -545,7 +545,7 @@ class qcdiag(metaclass=LogBase):
print_progress(prog, 100, prefix="Progress:", suffix=f"Complete, item {hex(item)}", bar_length=50)
old = prog
res, nvitem = self.read_nvitem(item)
if res != False:
if res:
if nvitem.status != 0x5:
nvitem.status = self.DecodeNVItems(nvitem)
nvitems.append(dict(id=nvitem.item, name=nvitem.name, data=hexlify(nvitem.data).decode("utf-8"),
@ -649,7 +649,7 @@ class qcdiag(metaclass=LogBase):
if len(res) > 0:
if res[0] == 0x27:
res, nvitem = self.read_nvitem(item)
if res == False:
if not res:
print(f"Error while writing nvitem {hex(item)} data, %s" % data)
else:
if nvitem.data != data:
@ -671,7 +671,7 @@ class qcdiag(metaclass=LogBase):
if len(res) > 0:
if res[0] == 0x4B:
res, nvitem = self.read_nvitemsub(item, index)
if res == False:
if not res:
print(f"Error while writing nvitem {hex(item)} index {hex(index)} data, %s" % data)
else:
if nvitem.data != data:
@ -809,7 +809,7 @@ class qcdiag(metaclass=LogBase):
return False
write_handle.close()
if efserr == False:
if not efserr:
print("Successfully read EFS.")
return True
else:
@ -1408,7 +1408,7 @@ def main():
parser_nvwritesub.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_writeimei = subparser.add_parser("writeimei", help="Write imei")
parser_writeimei.add_argument("imei", metavar=("<imei1,imei2,...>"), help="[Option] IMEI to write", default="")
parser_writeimei.add_argument("imei", metavar="<imei1,imei2,...>", help="[Option] IMEI to write", default="")
parser_writeimei.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_writeimei.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_writeimei.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",

View file

@ -17,6 +17,7 @@ import logging.config
import logging.handlers
import colorama
class ColorFormatter(logging.Formatter):
LOG_COLORS = {
logging.ERROR: colorama.Fore.RED,
@ -210,7 +211,8 @@ keytable = bytearray([0xF0, 0x14, 0x55, 0x0D, 0x5E, 0xDA, 0x92, 0xB3, 0xA7, 0x6C
0x46, 0x30, 0x33, 0x43, 0x44, 0x36, 0x42, 0x34, 0x41, 0x32, 0x31, 0x32, 0x30, 0x35, 0x39, 0x37
])
class SierraGenerator():
class SierraGenerator:
tbl = bytearray()
rtbl = bytearray()
devicegeneration = None
@ -425,7 +427,7 @@ class connection:
def readreply(self):
info = []
if self.serial is not None:
while (True):
while True:
tmp = self.serial.readline().decode('utf-8').replace('\r', '').replace('\n', '')
if "OK" in info:
return info
@ -464,7 +466,7 @@ class SierraKeygen(metaclass=LogBase):
def __init__(self, cn, devicegeneration=None):
self.cn = cn
self.keygen = SierraGenerator()
if devicegeneration == None:
if devicegeneration is None:
self.detectdevicegeneration()
else:
self.devicegeneration = devicegeneration
@ -506,7 +508,7 @@ class SierraKeygen(metaclass=LogBase):
devicegeneration = "MDM9x30_V1"
else:
devicegeneration = "MDM9x30"
elif "9X40" in revision and not "9X40C" in revision:
elif "9X40" in revision and "9X40C" not in revision:
devicegeneration = "MDM9x40"
elif "9X50" in revision:
if "NTG9X50" in revision:

View file

@ -7,9 +7,10 @@
# GPLv3 and has to be open sourced under GPLv3 as well. !!!!!
# TXT to EDL Loader (c) B.Kerler 2023
import os,sys
import sys
from struct import unpack
def main():
if len(sys.argv) < 2:
print("Usage: ./txt_to_loader.py [log.txt] [loader.elf]")
@ -53,5 +54,6 @@ def main():
print("Done.")
if __name__ == "__main__":
main()

View file

@ -1,5 +1,5 @@
# Challenge/Response Generator for Sierra Wireless Cards V1.2
(c) B. Kerler 2019-2023
(c) B. Kerler 2019-2024
GPLv3 License
## Why