Add multi-erase, beautify

This commit is contained in:
Bjoern Kerler 2022-06-28 13:53:44 +02:00
parent 3762ab9c9e
commit ad93c98404
No known key found for this signature in database
GPG key ID: 52E823BB96A55380
5 changed files with 210 additions and 204 deletions

9
edl
View file

@ -115,7 +115,7 @@ Options:
--skip=partnames Skip reading partition with names "partname1,partname2,etc."
--genxml Generate rawprogram[lun].xml
--devicemodel=value Set device model
--portname=portname Set serial port name (/dev/ttyUSB0 for Linux/MAC; \\.\COM1 for Windows)
--portname=portname Set serial port name (/dev/ttyUSB0 for Linux/MAC; \\\\.\\COM1 for Windows)
--serial Use serial port (port autodetection)
--slot Set active slot for setactiveslot [a or b]
--resetmode=mode Resetmode for reset (poweroff, reset, edl, etc.)
@ -155,6 +155,7 @@ def parse_cmd(rargs):
return cmd
return ""
def console_cmd(cmd):
read = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, close_fds=True)
@ -215,7 +216,7 @@ class main(metaclass=LogBase):
mode = resp["mode"]
self.info(f"Mode detected: {mode}")
return resp
return {"mode":"error"}
return {"mode": "error"}
def exit(self):
self.cdc.close()
@ -275,7 +276,7 @@ class main(metaclass=LogBase):
else:
self.portname = ""
if self.serial:
self.cdc = serial_class(loglevel=self.__logger.level,portconfig=portconfig)
self.cdc = serial_class(loglevel=self.__logger.level, portconfig=portconfig)
else:
self.cdc = usb_class(portconfig=portconfig, loglevel=self.__logger.level)
@ -290,7 +291,6 @@ 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"]
@ -381,6 +381,7 @@ class main(metaclass=LogBase):
if fh.connect(sahara):
fh.handle_firehose(cmd, options)
if __name__ == '__main__':
base = main()
base.run()

View file

@ -16,16 +16,18 @@ from edlclient.Library.gpt import gpt
from edlclient.Library.sparse import QCSparse
from edlclient.Library.utils import progress
class response:
resp=False
data=b""
error=""
log=None
def __init__(self, resp=False, data=b"", error:str="", log:dict=""):
self.resp=resp
self.data=data
self.error=error
self.log=log
resp = False
data = b""
error = ""
log = None
def __init__(self, resp=False, data=b"", error: str = "", log: dict = ""):
self.resp = resp
self.data = data
self.error = error
self.log = log
try:
@ -66,8 +68,8 @@ class nand_partition:
name, offset, length, attr1, attr2, attr3, which_flash = unpack("16sIIBBBB",
data[i * 0x1C:(i * 0x1C) + 0x1C])
np = partf()
if name[:2]==b"0:":
name=name[2:]
if name[:2] == b"0:":
name = name[2:]
np.name = name.rstrip(b"\x00").decode('utf-8').lower()
if self.parent.cfg.block_size == 0:
np.sector = offset
@ -80,7 +82,7 @@ class nand_partition:
np.attr3 = attr3
np.which_flash = which_flash
self.partentries[np.name] = np
if self.parent.cfg.block_size != 0 and self.parent.cfg.total_blocks!=0:
if self.parent.cfg.block_size != 0 and self.parent.cfg.total_blocks != 0:
self.totalsectors = (self.parent.cfg.block_size // self.parent.cfg.SECTOR_SIZE_IN_BYTES) * \
self.parent.cfg.total_blocks
else:
@ -252,7 +254,7 @@ class firehose(metaclass=LogBase):
rdata += tmp
except Exception as err:
self.error(err)
return response(resp=False,error=str(err))
return response(resp=False, error=str(err))
try:
if b"raw hex token" in rdata:
rdata = rdata
@ -260,7 +262,7 @@ class firehose(metaclass=LogBase):
resp = self.xml.getresponse(rdata)
status = self.getstatus(resp)
if "rawmode" in resp:
if resp["rawmode"]=="false":
if resp["rawmode"] == "false":
if status:
log = self.xml.getlog(rdata)
return response(resp=status, data=resp, log=log)
@ -280,9 +282,9 @@ class firehose(metaclass=LogBase):
if status:
return response(resp=True, data=resp)
else:
error=""
error = ""
if b"<log value" in rdata:
error=self.xml.getlog(rdata)
error = self.xml.getlog(rdata)
return response(resp=False, error=error, data=resp)
except Exception as err:
self.debug(str(err))
@ -294,14 +296,14 @@ class firehose(metaclass=LogBase):
", Error: " + str(err))
elif isinstance(rdata, str):
self.debug("Error on getting xml response:" + rdata)
return response(resp=False,error=rdata)
return response(resp=False, error=rdata)
else:
return response(resp=True,data=rdata)
return response(resp=True, data=rdata)
def cmd_reset(self, mode="reset"):
if mode is None:
mode = "poweroff"
data = "<?xml version=\"1.0\" ?><data><power value=\""+mode+"\"/></data>"
data = "<?xml version=\"1.0\" ?><data><power value=\"" + mode + "\"/></data>"
val = self.xmlsend(data)
try:
v = None
@ -319,7 +321,7 @@ class firehose(metaclass=LogBase):
self.info("Reset succeeded.")
return True
else:
self.error("Reset failed: "+val.error)
self.error("Reset failed: " + val.error)
return False
def cmd_xml(self, filename):
@ -335,7 +337,8 @@ class firehose(metaclass=LogBase):
def cmd_nop(self):
data = "<?xml version=\"1.0\" ?><data><nop /></data>"
resp=self.xmlsend(data, True)
resp = self.xmlsend(data, True)
self.debug(resp.hex())
info = b""
tmp = None
while tmp != b"":
@ -366,7 +369,7 @@ class firehose(metaclass=LogBase):
else:
return res
else:
self.error("GetSha256Digest failed: "+val.error)
self.error("GetSha256Digest failed: " + val.error)
return False
def cmd_setbootablestoragedrive(self, partition_number):
@ -379,9 +382,9 @@ class firehose(metaclass=LogBase):
self.error("Setbootablestoragedrive failed: " + val.error)
return False
def cmd_send(self, content, response=True):
def cmd_send(self, content, responsexml=True):
data = f"<?xml version=\"1.0\" ?><data>\n<{content} /></data>"
if response:
if responsexml:
val = self.xmlsend(data)
if val.resp:
return val.data
@ -630,12 +633,12 @@ class firehose(metaclass=LogBase):
progbar.show_progress(prefix="Read", pos=0, total=total, display=display)
while bytestoread > 0:
if self.cdc.is_serial:
maxsize=self.cfg.MaxPayloadSizeFromTargetInBytes
maxsize = self.cfg.MaxPayloadSizeFromTargetInBytes
else:
maxsize=5*1024*1024
size=min(maxsize, bytestoread)
maxsize = 5 * 1024 * 1024
size = min(maxsize, bytestoread)
data = usb_read(size)
if len(data)>0:
if len(data) > 0:
wr.write(data)
bytestoread -= len(data)
show_progress(prefix="Read", pos=total - bytestoread, total=total, display=display)
@ -698,22 +701,22 @@ class firehose(metaclass=LogBase):
self.error(f"Error:")
for line in info:
self.error(line)
return response(resp=False,data=resData, error=info)
return response(resp=False, data=resData, error=info)
elif "rawmode" in rsp:
if rsp["rawmode"] == "false":
return response(resp=True,data=resData)
return response(resp=True, data=resData)
else:
if len(rsp) > 1:
if b"Failed to open the UFS Device" in rsp[2]:
self.error(f"Error:{rsp[2]}")
self.lasterror = rsp[2]
return response(resp=False,data=resData,error=rsp[2])
if rsp["value"]!="ACK":
return response(resp=False, data=resData, error=rsp[2])
if rsp["value"] != "ACK":
self.lasterror = rsp[2]
if display and prog != 100:
progbar.show_progress(prefix="Read", pos=total, total=total, display=display)
resp=rsp["value"]=="ACK"
return response(resp=resp,data=resData,error=rsp[2]) # Do not remove, needed for oneplus
resp = rsp["value"] == "ACK"
return response(resp=resp, data=resData, error=rsp[2]) # Do not remove, needed for oneplus
def get_gpt(self, lun, gpt_num_part_entries, gpt_part_entry_size, gpt_part_entry_start_lba):
try:
@ -723,7 +726,7 @@ class firehose(metaclass=LogBase):
self.skipresponse = True
resp = self.cmd_read_buffer(lun, 0, 2, False)
if not resp.resp :
if not resp.resp:
for line in resp.error:
self.error(line)
return None, None
@ -734,11 +737,11 @@ class firehose(metaclass=LogBase):
self.info("Scanning for partition table ...")
progbar = progress(1)
if self.nandpart.partitiontblsector is None:
sector=0x280
sector = 0x280
progbar.show_progress(prefix="Scanning", pos=sector, total=1024, display=True)
resp = self.cmd_read_buffer(0, sector, 1, False)
if resp.resp:
if resp.data[0:8] in [b"\xac\x9f\x56\xfe\x7a\x12\x7f\xcd",b"\xAA\x73\xEE\x55\xDB\xBD\x5E\xE3"]:
if resp.data[0:8] in [b"\xac\x9f\x56\xfe\x7a\x12\x7f\xcd", b"\xAA\x73\xEE\x55\xDB\xBD\x5E\xE3"]:
progbar.show_progress(prefix="Scanning", pos=1024, total=1024, display=True)
self.nandpart.partitiontblsector = sector
self.info(f"Found partition table at sector {sector} :)")
@ -849,10 +852,10 @@ class firehose(metaclass=LogBase):
'''
rsp = self.xmlsend(connectcmd)
if not rsp.resp:
if rsp.error=="":
if rsp.error == "":
try:
if "MemoryName" in rsp.data:
self.cfg.MemoryName = rsp.data["MemoryName"]
self.cfg.MemoryName = rsp.data["MemoryName"]
except TypeError:
self.warning("!DEBUG! rsp.data: '%s'" % (rsp.data,))
return self.configure(lvl + 1)
@ -861,7 +864,8 @@ class firehose(metaclass=LogBase):
if "MaxPayloadSizeToTargetInBytes" in rsp.data:
self.cfg.MaxPayloadSizeToTargetInBytes = int(rsp.data["MaxPayloadSizeToTargetInBytes"])
if "MaxPayloadSizeToTargetInBytesSupported" in rsp.data:
self.cfg.MaxPayloadSizeToTargetInBytesSupported = int(rsp.data["MaxPayloadSizeToTargetInBytesSupported"])
self.cfg.MaxPayloadSizeToTargetInBytesSupported = int(
rsp.data["MaxPayloadSizeToTargetInBytesSupported"])
if "TargetName" in rsp.data:
self.cfg.TargetName = rsp.data["TargetName"]
return self.configure(lvl + 1)
@ -924,7 +928,7 @@ class firehose(metaclass=LogBase):
self.warning(line)
else:
info = self.cdc.read(timeout=1)
if isinstance(rsp.resp,dict):
if isinstance(rsp.resp, dict):
field = rsp.resp
if "MemoryName" not in field:
# print(rsp[1])
@ -945,7 +949,8 @@ class firehose(metaclass=LogBase):
else:
self.cfg.MaxPayloadSizeToTargetInBytes = 1048576
if "MaxPayloadSizeToTargetInBytesSupported" in field:
self.cfg.MaxPayloadSizeToTargetInBytesSupported = int(field["MaxPayloadSizeToTargetInBytesSupported"])
self.cfg.MaxPayloadSizeToTargetInBytesSupported = int(
field["MaxPayloadSizeToTargetInBytesSupported"])
else:
self.cfg.MaxPayloadSizeToTargetInBytesSupported = 1048576
if "MaxXMLSizeInBytes" in field:
@ -992,11 +997,11 @@ class firehose(metaclass=LogBase):
"Memory type UFS doesn't seem to match (Failed to init). Trying to use eMMC instead.")
self.cfg.MemoryName = "eMMC"
return self.configure(0)
elif "Attribute \'SECTOR_SIZE_IN_BYTES\'=4096 must be equal to disk sector size 512" in line\
elif "Attribute \'SECTOR_SIZE_IN_BYTES\'=4096 must be equal to disk sector size 512" in line \
or "different from device sector size (512)" in line:
self.cfg.SECTOR_SIZE_IN_BYTES = 512
return self.configure(0)
elif "Attribute \'SECTOR_SIZE_IN_BYTES\'=512 must be equal to disk sector size 4096" in line\
elif "Attribute \'SECTOR_SIZE_IN_BYTES\'=512 must be equal to disk sector size 4096" in line \
or "different from device sector size (4096)" in line:
self.cfg.SECTOR_SIZE_IN_BYTES = 4096
return self.configure(0)
@ -1011,8 +1016,8 @@ class firehose(metaclass=LogBase):
int(self.args["--gpt-part-entry-size"]),
int(self.args["--gpt-part-entry-start-lba"]))
self.lunsizes[lun] = guid_gpt.totalsectors
except Exception as e:
self.error(e)
except Exception as err:
self.error(err)
return -1
else:
return self.lunsizes[lun]
@ -1090,7 +1095,7 @@ class firehose(metaclass=LogBase):
if info == [] or (len(info) > 0 and 'ERROR' in info[0]):
if len(info) > 0:
self.debug(info[0])
if len(info)>0:
if len(info) > 0:
supfunc = False
for line in info:
self.info(line)
@ -1110,11 +1115,11 @@ class firehose(metaclass=LogBase):
if "supported functions" in line.lower():
supfunc = True
if "program" in line.lower():
idx=line.find("Functions: ")
if idx!=-1:
v=line[idx+11:].split(" ")
idx = line.find("Functions: ")
if idx != -1:
v = line[idx + 11:].split(" ")
for val in v:
if val!="":
if val != "":
self.supported_functions.append(val)
supfunc = False
try:
@ -1154,7 +1159,7 @@ class firehose(metaclass=LogBase):
def parse_storage(self):
storageinfo = self.cmd_getstorageinfo()
if storageinfo is None or storageinfo.resp and len(storageinfo.data)==0:
if storageinfo is None or storageinfo.resp and len(storageinfo.data) == 0:
return False
info = storageinfo.data
if "UFS Inquiry Command Output" in info:
@ -1193,18 +1198,18 @@ class firehose(metaclass=LogBase):
def cmd_getstorageinfo(self):
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:
if val.data == '' and val.log == '' and val.resp:
return None
if isinstance(val.data,dict):
if isinstance(val.data, dict):
if "bNumberLu" in val.data:
self.cfg.maxlun = int(val.data["bNumberLu"])
if val.resp:
if val.log is not None:
res={}
res = {}
for value in val.log:
v=value.split("=")
if len(v)>1:
res[v[0]]=v[1]
v = value.split("=")
if len(v) > 1:
res[v[0]] = v[1]
else:
if "\"storage_info\"" in value:
try:
@ -1229,23 +1234,23 @@ class firehose(metaclass=LogBase):
if "prod_name" in si:
self.cfg.prod_name = si["prod_name"]
else:
v=value.split(":")
if len(v)>1:
res[v[0]]=v[1].lstrip(" ")
v = value.split(":")
if len(v) > 1:
res[v[0]] = v[1].lstrip(" ")
return response(resp=val.resp, data=res)
return response(resp=val.resp, data=val.data)
else:
if val.error:
for v in val.error:
if "Failed to open the SDCC Device" in v:
self.cfg.MemoryName="ufs"
self.cfg.MemoryName = "ufs"
self.configure(0)
return self.cmd_getstorageinfo()
self.warning("GetStorageInfo command isn't supported.")
return None
def cmd_setactiveslot(self, slot:str):
if slot.lower() not in ["a","b"]:
def cmd_setactiveslot(self, slot: str):
if slot.lower() not in ["a", "b"]:
self.error("Only slots a or b are accepted. Aborting.")
return False
partslots = {}
@ -1275,8 +1280,8 @@ class firehose(metaclass=LogBase):
byte_offset_patch = poffset % self.cfg.SECTOR_SIZE_IN_BYTES
headeroffset = gp.header.current_lba * gp.sectorsize
start_sector_hdr = headeroffset // self.cfg.SECTOR_SIZE_IN_BYTES
header = wdata[start_sector_hdr:start_sector_hdr+gp.header.header_size]
self.cmd_patch(lun,start_sector_patch,byte_offset_patch,pdata,len(pdata),True)
header = wdata[start_sector_hdr:start_sector_hdr + gp.header.header_size]
self.cmd_patch(lun, start_sector_patch, byte_offset_patch, pdata, len(pdata), True)
self.cmd_patch(lun, headeroffset, 0, header, len(pdata), True)
return True
return False
@ -1348,8 +1353,8 @@ class firehose(metaclass=LogBase):
f"SizeInBytes=\"{str(maxsize)}\" value64=\"{content}\" /></data>\n"
try:
self.cdc.write(xdata[:self.cfg.MaxXMLSizeInBytes])
except Exception as e: # pylint: disable=broad-except
self.debug(str(e))
except Exception as err: # pylint: disable=broad-except
self.debug(str(err))
pass
addrinfo = self.cdc.read(timeout=None)
if b"SizeInBytes" in addrinfo or b"Invalid parameters" in addrinfo:

View file

@ -785,6 +785,8 @@ class firehose_client(metaclass=LogBase):
return False
luns = self.getluns(options)
partitionname = options["<partitionname>"]
partitions = partitionname.split(",")
error = False
for lun in luns:
data, guid_gpt = self.firehose.get_gpt(lun, int(options["--gpt-num-part-entries"]),
int(options["--gpt-part-entry-size"]),
@ -793,20 +795,21 @@ class firehose_client(metaclass=LogBase):
break
if self.firehose.modules is not None:
self.firehose.modules.writeprepare()
if partitionname in guid_gpt.partentries:
partition = guid_gpt.partentries[partitionname]
self.firehose.cmd_erase(lun, partition.sector, partition.sectors)
self.printer(
f"Erased {partitionname} starting at sector {str(partition.sector)} " +
f"with sector count {str(partition.sectors)}.")
return True
else:
self.printer(
f"Couldn't erase partition {partitionname}. Either wrong memorytype given or no gpt partition.")
return False
self.error(f"Error: Couldn't detect partition: {partitionname}")
return False
for partitionname in partitions:
if partitionname in guid_gpt.partentries:
partition = guid_gpt.partentries[partitionname]
self.firehose.cmd_erase(lun, partition.sector, partition.sectors)
self.printer(
f"Erased {partitionname} starting at sector {str(partition.sector)} " +
f"with sector count {str(partition.sectors)}.")
else:
self.printer(
f"Couldn't erase partition {partitionname}. Either wrong memorytype given or no gpt partition.")
error = True
continue
if error:
return False
return True
elif cmd == "ep":
if not self.check_param(["<partitionname>", "<sectors>"]):
return False

View file

@ -220,11 +220,11 @@ def main(argv):
if len(argv) < 3:
print("Usage: fhloaderparse [FHLoaderDir] [OutputDir]")
exit(0)
else:
path = argv[1]
outputdir = argv[2]
if not os.path.exists(outputdir):
os.mkdir(outputdir)
path = argv[1]
outputdir = argv[2]
if not os.path.exists(outputdir):
os.mkdir(outputdir)
# First hash all loaders in Loader directory
hashes = {}

View file

@ -12,6 +12,7 @@ from enum import Enum
from struct import unpack, pack
from binascii import hexlify, unhexlify
import os, sys
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(os.path.dirname(current_dir))
sys.path.insert(0, parent_dir)
@ -342,7 +343,7 @@ class qcdiag(metaclass=LogBase):
def prettyprint(self, data):
recv = ""
plain = ""
if len(data)==0:
if len(data) == 0:
return ""
for i in range(len(data)):
inf = "%02X " % data[i]
@ -378,9 +379,9 @@ class qcdiag(metaclass=LogBase):
else:
return "Command accepted"
def connect(self, serial:bool = False):
def connect(self, serial: bool = False):
if serial:
self.cdc = serial_class(loglevel=self.__logger.level,portconfig=self.portconfig)
self.cdc = serial_class(loglevel=self.__logger.level, portconfig=self.portconfig)
else:
self.cdc = usb_class(portconfig=self.portconfig, loglevel=self.__logger.level)
self.hdlc = None
@ -414,13 +415,12 @@ class qcdiag(metaclass=LogBase):
def enter_saharamode(self):
self.hdlc.receive_reply(timeout=0)
res = self.send(b"\x4b\x65\x01\x00")
if res[0]==0x4b:
if res[0] == 0x4b:
print("Done, switched to edl")
else:
print("Error switching to edl. Try again.")
self.disconnect()
def send_sp(self, sp="FFFFFFFFFFFFFFFFFFFE"):
if type(sp) == str:
sp = unhexlify(sp)
@ -504,13 +504,13 @@ class qcdiag(metaclass=LogBase):
print(nvitem)
def print_nvitemsub(self, item, index):
res, nvitem = self.read_nvitemsub(item,index)
res, nvitem = self.read_nvitemsub(item, index)
info = self.DecodeNVItems(nvitem)
if res != False:
if nvitem.name != "":
ItemNumber = f"{hex(item),hex(index)} ({nvitem.name}): "
ItemNumber = f"{hex(item), hex(index)} ({nvitem.name}): "
else:
ItemNumber = hex(item)+","+hex(index) + ": "
ItemNumber = hex(item) + "," + hex(index) + ": "
returnanswer = "NVItem " + ItemNumber + info
print(returnanswer)
if nvitem.status == 0:
@ -549,7 +549,7 @@ class qcdiag(metaclass=LogBase):
write_handle.write(errors)
print("Done.")
def unpackdata(self,data):
def unpackdata(self, data):
rlen = len(data)
idx = rlen - 1
for i in range(0, rlen):
@ -572,8 +572,8 @@ class qcdiag(metaclass=LogBase):
name = ""
if item in self.nvlist:
name = self.nvlist[item]
data=self.unpackdata(res["rawdata"])
res = nvitem(res["item"],0, data, res["status"], name)
data = self.unpackdata(res["rawdata"])
res = nvitem(res["item"], 0, data, res["status"], name)
return [True, res]
elif data[0] == 0x14:
return [False, f"Error 0x14 trying to read nvitem {hex(item)}."]
@ -594,7 +594,7 @@ class qcdiag(metaclass=LogBase):
name = ""
if item in self.nvlist:
name = self.nvlist[item]
data=self.unpackdata(res["rawdata"])
data = self.unpackdata(res["rawdata"])
res = nvitem(res["item"], index, data, res["status"], name)
return [True, res]
elif data[0] == 0x14:
@ -603,27 +603,27 @@ class qcdiag(metaclass=LogBase):
return [False, f"Error {hex(data[0])} trying to read nvitem {hex(item)}."]
return [False, f"Empty request for nvitem {hex(item)}"]
def convertimei(self,imei):
data=imei[0]+"A"
for i in range(1,len(imei),2):
data+=imei[i+1]
data+=imei[i]
return unhexlify("08"+data)
def convertimei(self, imei):
data = imei[0] + "A"
for i in range(1, len(imei), 2):
data += imei[i + 1]
data += imei[i]
return unhexlify("08" + data)
def write_imei(self,imeis):
def write_imei(self, imeis):
if "," in imeis:
imeis=imeis.split(",")
imeis = imeis.split(",")
else:
imeis=[imeis]
index=0
imeis = [imeis]
index = 0
for imei in imeis:
data=self.convertimei(imei)
if index==0:
if not self.write_nvitem(550,data):
self.write_nvitemsub(550,index,data)
data = self.convertimei(imei)
if index == 0:
if not self.write_nvitem(550, data):
self.write_nvitemsub(550, index, data)
else:
self.write_nvitemsub(550,index,data)
index+=1
self.write_nvitemsub(550, index, data)
index += 1
def write_nvitem(self, item, data):
rawdata = bytes(data)
@ -656,12 +656,13 @@ class qcdiag(metaclass=LogBase):
res = self.send(nvrequest)
if len(res) > 0:
if res[0] == 0x4B:
res, nvitem = self.read_nvitemsub(item,index)
res, nvitem = self.read_nvitemsub(item, index)
if res == False:
print(f"Error while writing nvitem {hex(item)} index {hex(index)} data, %s" % data)
else:
if nvitem.data != data:
print(f"Error while writing nvitem {hex(item)} index {hex(index)} data, verified data doesn't match")
print(
f"Error while writing nvitem {hex(item)} index {hex(index)} data, verified data doesn't match")
else:
print(f"Successfully wrote nvitem {hex(item)} index {hex(index)}.")
return True
@ -882,12 +883,12 @@ class qcdiag(metaclass=LogBase):
if len(resp) > 0:
[dirp, seqno, diag_errno, entry_type, mode, size, atime, mtime, ctime] = unpack("<Iiiiiiiii",
resp[4:4 + (9 * 4)])
if entry_type==1:
if entry_type == 1:
entry_name = resp[4 + (9 * 4):-1]
if len(entry_name)<50:
entry_name+=(50-len(entry_name))*b" "
if len(entry_name) < 50:
entry_name += (50 - len(entry_name)) * b" "
info += f"{path}{entry_name.decode('utf-8')} mode:{hex(mode)}, size:{hex(size)}, atime:{hex(atime)}, mtime:{hex(mtime)}, ctime:{hex(ctime)}\n"
elif entry_type==0:
elif entry_type == 0:
break
if self.efs_closedir(efsmethod, dirp) != 0:
print("Error on listing directory")
@ -1179,37 +1180,37 @@ class DiagTools(metaclass=LogBase):
if connected:
cmd = args.cmd
if cmd=="sp":
if cmd == "sp":
diag.send_sp(args.spval)
elif cmd=="spc":
elif cmd == "spc":
diag.send_spc(args.spcval)
elif cmd=="cmd":
if args.cmdval=="":
elif cmd == "cmd":
if args.cmdval == "":
print("cmd needed as hex string, example: 00")
else:
print(diag.send_cmd(args.cmdval))
elif cmd=="info":
elif cmd == "info":
print(diag.cmd_info())
elif cmd=="download":
elif cmd == "download":
diag.enter_downloadmode()
elif cmd=="sahara":
elif cmd == "sahara":
diag.enter_saharamode()
elif cmd=="crash":
elif cmd == "crash":
diag.enforce_crash()
elif cmd=="efslistdir":
elif cmd == "efslistdir":
print(diag.efslistdir(args.path))
elif cmd=="efsreadfile":
if args.src=="" or args.dst=="":
elif cmd == "efsreadfile":
if args.src == "" or args.dst == "":
print("Usage: -efsreadfile -src srcfile -dst dstfile")
sys.exit()
print(diag.efsreadfile(args.src,args.dst))
elif cmd=="nvread":
print(diag.efsreadfile(args.src, args.dst))
elif cmd == "nvread":
if "0x" in args.nvitem:
nvitem = int(args.nvitem, 16)
else:
nvitem = int(args.nvitem)
diag.print_nvitem(nvitem)
elif cmd=="nvreadsub":
elif cmd == "nvreadsub":
if args.nvitem is None or args.nvindex is None:
print("Usage: nvreadsub [nvitem] [nvindex]")
exit(1)
@ -1222,8 +1223,8 @@ class DiagTools(metaclass=LogBase):
nvindex = int(args.nvindex, 16)
else:
nvindex = int(args.nvindex)
diag.print_nvitemsub(nvitem,nvindex)
elif cmd=="nvwrite":
diag.print_nvitemsub(nvitem, nvindex)
elif cmd == "nvwrite":
if args.data is None:
print("NvWrite requires data to write")
sys.exit()
@ -1233,7 +1234,7 @@ class DiagTools(metaclass=LogBase):
nvitem = int(args.nvitem)
data = unhexlify(args.data)
diag.write_nvitem(nvitem, data)
elif cmd=="nvwritesub":
elif cmd == "nvwritesub":
if args.nvitem is None or args.nvindex is None or args.data is None:
print("NvWriteSub requires item, index and data to write")
sys.exit()
@ -1247,11 +1248,11 @@ class DiagTools(metaclass=LogBase):
nvindex = int(args.nvindex)
data = unhexlify(args.data)
diag.write_nvitemsub(nvitem, nvindex, data)
elif cmd=="nvbackup":
elif cmd == "nvbackup":
diag.backup_nvitems(args.filename, "error.log")
elif cmd=="writeimei":
elif cmd == "writeimei":
diag.write_imei(args.imei)
elif cmd=="efsread":
elif cmd == "efsread":
diag.efsread(args.filename)
else:
print("A command is required. Use -cmd \"data\" for sending requests.")
@ -1259,8 +1260,8 @@ class DiagTools(metaclass=LogBase):
print("Valid commands are:")
print("-------------------")
print("info cmd sp spc nvread nvreadsub" +
" nvwrite writeimei nvwritesub nvbackup efsread efsreadfile" +
" efslistdir download sahara crash")
" nvwrite writeimei nvwritesub nvbackup efsread efsreadfile" +
" efslistdir download sahara crash")
print()
diag.disconnect()
sys.exit()
@ -1275,54 +1276,53 @@ def main():
parser = argparse.ArgumentParser(description=info)
print("\n" + info + "\n---------------------------------------\n")
subparser = parser.add_subparsers(dest="cmd", help="Valid commands are:\ninfo cmd sp spc nvread nvreadsub" +
" nvwrite writeimei nvwritesub nvbackup efsread efsreadfile\n" +
" efslistdir download sahara crash")
" nvwrite writeimei nvwritesub nvbackup efsread efsreadfile\n" +
" efslistdir download sahara crash")
parser_info = subparser.add_parser("info", help="[Option] Get diag info")
parser_info.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_info.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_info.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_info.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_info.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_info.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_info.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_cmd = subparser.add_parser("cmd", help="Send command")
parser_cmd.add_argument("cmdval", help="cmd to send (hexstring), default: 00",
default="", const="00", nargs="?")
default="", const="00", nargs="?")
parser_cmd.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_cmd.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_cmd.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_cmd.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_cmd.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_cmd.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_cmd.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_sp = subparser.add_parser("sp", help="Send Security password")
parser_sp.add_argument("spval", help="Security password to send, default: FFFFFFFFFFFFFFFE",
default="FFFFFFFFFFFFFFFE", nargs="?")
default="FFFFFFFFFFFFFFFE", nargs="?")
parser_sp.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_sp.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_sp.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_sp.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_sp.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_sp.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_sp.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_spc = subparser.add_parser("spc", help="Send Security Code")
parser_spc.add_argument("spcval", help="Security code to send, default: 303030303030",
default="303030303030", nargs="?")
default="303030303030", nargs="?")
parser_spc.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_spc.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_spc.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_spc.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_spc.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_spc.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_spc.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_nvread = subparser.add_parser("nvread", help="Read nvitem")
@ -1330,10 +1330,10 @@ def main():
parser_nvread.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_nvread.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_nvread.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_nvread.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvread.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvread.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_nvread.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_nvreadsub = subparser.add_parser("nvreadsub", help="Read nvitem using subsystem")
@ -1342,10 +1342,10 @@ def main():
parser_nvreadsub.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_nvreadsub.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_nvreadsub.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_nvreadsub.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvreadsub.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvreadsub.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_nvreadsub.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_nvwrite = subparser.add_parser("nvwrite", help="Write nvitem")
@ -1354,10 +1354,10 @@ def main():
parser_nvwrite.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_nvwrite.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_nvwrite.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_nvwrite.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvwrite.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvwrite.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_nvwrite.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_nvwritesub = subparser.add_parser("nvwritesub", help="Write nvitem using subsystem")
@ -1367,10 +1367,10 @@ def main():
parser_nvwritesub.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_nvwritesub.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_nvwritesub.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_nvwritesub.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvwritesub.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvwritesub.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_nvwritesub.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_writeimei = subparser.add_parser("writeimei", help="Write imei")
@ -1378,22 +1378,21 @@ def main():
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)",
default="0")
default="0")
parser_writeimei.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_writeimei.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_writeimei.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_writeimei.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_nvbackup = subparser.add_parser("nvbackup", help="Make nvitem backup as json")
parser_nvbackup.add_argument("filename", help="[Option] Filename to write to", default="")
parser_nvbackup.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_nvbackup.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_nvbackup.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_nvbackup.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvbackup.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_nvbackup.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_nvbackup.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_efsread = subparser.add_parser("efsread", help="Read efs")
@ -1401,10 +1400,10 @@ def main():
parser_efsread.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_efsread.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_efsread.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_efsread.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_efsread.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_efsread.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_efsread.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_efsreadfile = subparser.add_parser("efsreadfile", help="Read efs file")
@ -1413,10 +1412,10 @@ def main():
parser_efsreadfile.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_efsreadfile.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_efsreadfile.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_efsreadfile.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_efsreadfile.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_efsreadfile.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_efsreadfile.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_efslistdir = subparser.add_parser("efslistdir", help="List efs directory")
@ -1424,43 +1423,42 @@ def main():
parser_efslistdir.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_efslistdir.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_efslistdir.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_efslistdir.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_efslistdir.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_efslistdir.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_efslistdir.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_download = subparser.add_parser("download", help="[Option] Switch to sahara mode")
parser_download.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_download.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_download.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_download.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_download.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_download.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_download.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_sahara = subparser.add_parser("sahara", help="[Option] Switch to sahara mode")
parser_sahara.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_sahara.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_sahara.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_sahara.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_sahara.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_sahara.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_sahara.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
parser_crash = subparser.add_parser("crash", help="[Option] Enforce crash")
parser_crash.add_argument("-vid", metavar="<vid>", help="[Option] Specify vid", default="")
parser_crash.add_argument("-pid", metavar="<pid>", help="[Option] Specify pid", default="")
parser_crash.add_argument("-interface", metavar="<pid>", help="[Option] Specify interface number, default=0)",
default="0")
default="0")
parser_crash.add_argument("-portname", metavar="<portname>",
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_crash.add_argument("-serial",help="[Option] Use serial port (autodetect)", action="store_true")
help="[Option] Specify serial port (\"/dev/ttyUSB0\",\"COM1\")")
parser_crash.add_argument("-serial", help="[Option] Use serial port (autodetect)", action="store_true")
parser_crash.add_argument("-debugmode", help="[Option] Enable verbose logging", action="store_true")
args = parser.parse_args()
dg = DiagTools()
dg.run(args)
@ -1468,4 +1466,3 @@ def main():
if __name__ == "__main__":
main()