diff --git a/edl b/edl index f5ab206..4870aae 100755 --- a/edl +++ b/edl @@ -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() diff --git a/edlclient/Library/firehose.py b/edlclient/Library/firehose.py index cc1e281..fede758 100755 --- a/edlclient/Library/firehose.py +++ b/edlclient/Library/firehose.py @@ -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"" + 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 = "" - 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"\n<{content} />" - 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 = "" 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}\" />\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: diff --git a/edlclient/Library/firehose_client.py b/edlclient/Library/firehose_client.py index 45fe3f2..f5e81fb 100644 --- a/edlclient/Library/firehose_client.py +++ b/edlclient/Library/firehose_client.py @@ -785,6 +785,8 @@ class firehose_client(metaclass=LogBase): return False luns = self.getluns(options) partitionname = options[""] + 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(["", ""]): return False diff --git a/edlclient/Tools/fhloaderparse b/edlclient/Tools/fhloaderparse index e9d7d48..da9141c 100755 --- a/edlclient/Tools/fhloaderparse +++ b/edlclient/Tools/fhloaderparse @@ -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 = {} diff --git a/edlclient/Tools/qc_diag.py b/edlclient/Tools/qc_diag.py index 8a4ebf3..605516a 100755 --- a/edlclient/Tools/qc_diag.py +++ b/edlclient/Tools/qc_diag.py @@ -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("