def backup_nvitems(self, filename, errorlog=""): nvitems = [] pos = 0 old = 0 errors = "" print("Dumping nvitems 0x0 to 0xFFFF.") for item in range(0, 0xFFFF): prog = int(float(pos) / float(0xFFFF) * float(100)) if prog > old: 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 nvitem.status != 0x5: nvitem.status = self.DecodeNVItems(nvitem) nvitems.append(dict(id=nvitem.item, name=nvitem.name, data=hexlify(nvitem.data).decode('utf-8'), status=nvitem.status)) else: errors += nvitem + "\n" pos += 1 js = json.dumps(nvitems) with open(filename, "w") as write_handle: write_handle.write(js) if errorlog == "": print(errors) else: with open(errorlog, "w") as write_handle: write_handle.write(errors) print("Done.")
def sdmmc_write_image(self, addr, length, filename, display=True): if filename != "": with open(filename, "rb") as rf: if self.daconfig.flashtype == "emmc": self.usbwrite(self.Cmd.SDMMC_WRITE_IMAGE_CMD) # 61 self.usbwrite(b"\x00") # checksum level 0 self.usbwrite(b"\x08") # EMMC_PART_USER self.usbwrite(pack(">Q", addr)) self.usbwrite(pack(">Q", length)) self.usbwrite(b"\x08") # index 8 self.usbwrite(b"\x03") packetsize = unpack(">I", self.usbread(4))[0] ack = unpack(">B", self.usbread(1))[0] if ack == self.Rsp.ACK[0]: self.usbwrite(self.Rsp.ACK) if display: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) old = 0 checksum = 0 bytestowrite = length while bytestowrite > 0: size = min(bytestowrite, packetsize) for i in range(0, size, 0x400): data = bytearray(rf.read(size)) pos = length - bytestowrite if display: prog = pos / length * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex(pos), bar_length=50) old = round(prog, 1) if self.usbwrite(data): bytestowrite -= size if bytestowrite == 0: checksum = 0 for val in data: checksum += val checksum = checksum & 0xFFFF self.usbwrite(pack(">H", checksum)) if self.usbread(1) == b"\x69": if bytestowrite == 0: self.usbwrite(pack(">H", checksum)) if self.usbread(1) == self.Rsp.ACK: return True else: self.usbwrite(self.Rsp.ACK) return True return True
def dump_brom(self, filename): old = 0 try: with open(filename, 'wb') as wf: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) for addr in range(0x0, 0x20000, 16): prog = int(addr / 0x20000 * 100) if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr, bar_length=50) old = round(prog, 1) wf.write(self.mtk.port.usbread(16)) print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) return True except Exception as e: self.error(f"Error on opening {filename} for writing: {str(e)}") return False
def rpmb(self, start, length, filename, reverse=False): if start == 0: start = 0 else: start = (start // 0x100) if length == 0: sectors = 4 * 1024 * 1024 // 0x100 else: sectors = (length // 0x100) + (1 if length % 0x100 else 0) self.info("Reading rpmb...") self.cdc.usbwrite(pack(">I", 0xf00dd00d)) self.cdc.usbwrite(pack(">I", 0x1002)) self.cdc.usbwrite(pack(">I", 0x1)) # kick-wdt self.cdc.usbwrite(pack(">I", 0xf00dd00d)) self.cdc.usbwrite(pack(">I", 0x3001)) print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) bytesread = 0 old = 0 bytestoread = sectors * 0x100 with open(filename, "wb") as wf: for sector in range(start, sectors): self.cdc.usbwrite(pack(">I", 0xf00dd00d)) self.cdc.usbwrite(pack(">I", 0x2000)) self.cdc.usbwrite(pack(">H", sector)) tmp = self.cdc.usbread(0x100, 0x100) if reverse: tmp = tmp[::-1] if len(tmp) != 0x100: self.error("Error on getting data") return prog = sector / sectors * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex((sectors * 0x200) - bytestoread), bar_length=50) old = round(prog, 1) bytesread += 0x100 size = min(bytestoread, len(tmp)) wf.write(tmp[:size]) bytestoread -= size print_progress(100, 100, prefix='Complete: ', suffix=filename, bar_length=50) print("Done")
def dump_brom(self, filename, btype): if btype == "gcpu" and self.chipconfig.gcpu_base is None: self.error("Chipconfig has no gcpu_base field for this cpu") return False elif btype == "cqdma" and self.chipconfig.cqdma_base is None or self.chipconfig.ap_dma_mem is None: self.error( "Chipconfig has no cqdma_base and/or ap_dma_mem field for this cpu" ) return False if self.chipconfig.blacklist: self.disable_range_blacklist(btype) self.info("Dump bootrom") print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) old = 0 with open(filename, 'wb') as wf: for addr in range(0x0, 0x20000, 16): prog = int(addr / 0x20000 * 100) if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr, bar_length=50) old = round(prog, 1) if btype == "gcpu": wf.write(self.gcpu.aes_read_cbc(addr)) elif btype == "cqdma": if not self.chipconfig.blacklist: wf.write(self.cqdma.mem_read(addr, 16, True)) else: wf.write(self.cqdma.mem_read(addr, 16, False)) print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) return True
def efsread(self, filename): alternateefs = b"\x4B\x3E\x19\x00" standardefs = b"\x4B\x13\x19\x00" resp = self.send(alternateefs) if resp[0] == 0x4B: efsmethod = 0x3E else: resp = self.send(standardefs) if resp[0] == 0x4B: efsmethod = 0x13 else: print("No known efs method detected for reading.") return if filename == "": return False write_handle = open(filename, 'wb') if write_handle is None: print("Error on writing file ....") return False print("Reading EFS ....") fefs = fs_factimage_read_info(0, 0, 0, 0) # EFS Cmd buf = pack('<BBBB', 0x4B, efsmethod, efs_cmds.EFS2_DIAG_PREP_FACT_IMAGE.value, 0x00) # prepare factory image resp = self.send(buf) if len(resp) == 0: print( "Phone does not respond. Maybe another software is blocking the port." ) return False buf = pack('<BBBB', 0x4B, efsmethod, efs_cmds.EFS2_DIAG_FACT_IMAGE_START.value, 0x00) # indicate start read out factory image resp = self.send(buf) # EFS Cmd buf = pack('<BBBBBBHI', 0x4B, efsmethod, efs_cmds.EFS2_DIAG_FACT_IMAGE_READ.value, 0x00, fefs.stream_state, fefs.info_cluster_sent, fefs.cluster_map_seqno, fefs.cluster_data_seqno) resp = self.send(buf) if resp == 0 or resp == -1: info = ("Page %08X error !\n" % fefs.cluster_data_seqno) print(info) resp = self.send(buf) if resp == 0 or resp == -1: print("Data Error occured, ") + info error = unpack("<I", resp[4:8])[0] if (resp[0] == 0x13) or (resp[0] == 0x14) or (resp[0] == 0x15) or (error != 0x0): print("EFS Read not supported by phone. Aborting") write_handle.close() return False elif resp[0] == 0x47: print("Send Security Password (SP) first !") write_handle.close() return False efserr = False fh = FactoryHeader() if len(resp) > 0: write_handle.write(resp[0x10:-0x1]) fefs.fromdata(resp[0x8:0x10]) fh.fromdata(resp[0x10:0x10 + (39 * 4)]) old = 0 print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) total = fh.block_size * fh.block_count * (fh.page_size // 0x200) # Real start for page in range(0, total): # EFS Cmd buf = pack('<BBBBBBHI', 0x4B, efsmethod, efs_cmds.EFS2_DIAG_FACT_IMAGE_READ.value, 0x00, fefs.stream_state, fefs.info_cluster_sent, fefs.cluster_map_seqno, fefs.cluster_data_seqno) pos = int(page / total * 100) if pos > old: print_progress(pos, 100, prefix='Progress:', suffix='Page %d of %d' % (page, total), bar_length=50) old = pos resp = self.send(buf) if resp == 0: resp = self.send(buf) if resp == 0 or resp == -1: info = ("Page %08X !\n" % fefs.cluster_data_seqno) print(info) resp = self.send(buf) if resp == 0 or resp == -1: print("Data Error occured, " + info) else: dlen = len(resp) - 0x11 if dlen == 0x200 or dlen == 0x800: if resp[0x0] == 0x4B: write_handle.write(resp[0x10:0x10 + dlen]) fefs.fromdata(resp[0x8:0x10]) else: if (resp[0x0] == 0x13) and (resp[0x1] == 0x62) and (len(resp) > 0x200): write_handle.write(resp[0x14:-4]) fefs.fromdata(resp[0xc:0x14]) if fefs.stream_state == 0x0: break else: print( "EFS Read error : Wrong size recieved at page %X" % page) efserr = True break print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) buf = bytearray() buf.append(0x4B) buf.append(efsmethod) buf.append( efs_cmds.EFS2_DIAG_FACT_IMAGE_END.value) # end factory image buf.append(0x00) resp = self.send(buf) if len(resp) == 0: print( "Phone does not respond. Maybe another software is blocking the port." ) return False write_handle.close() if efserr == False: print("Successfully read EFS.") return True else: print("Error on reading EFS.") return False
total = SECTOR_SIZE_IN_BYTES * num_partition_sectors old = 0 pos = 0 while fsize > 0: wlen = MaxPayloadSizeToTargetInBytes // SECTOR_SIZE_IN_BYTES * SECTOR_SIZE_IN_BYTES if fsize < wlen: wlen = fsize wdata = sp.read(wlen) bytesToWrite -= wlen fsize -= wlen pos += wlen pv = wlen % SECTOR_SIZE_IN_BYTES if pv != 0: filllen = (wlen // SECTOR_SIZE_IN_BYTES * SECTOR_SIZE_IN_BYTES) + \ SECTOR_SIZE_IN_BYTES wdata += b"\x00" * (filllen - wlen) wlen = len(wdata) wf.write(wdata) prog = round(float(pos) / float(total) * float(100), 1) if prog > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete (Sector %d)' % (pos // SECTOR_SIZE_IN_BYTES), bar_length=50) print("Done.")
def readflash(self, addr, length, filename, parttype=None, display=True): if parttype is None or parttype == "user": parttype = PartitionType.MTK_DA_EMMC_PART_USER elif parttype == "boot1": parttype = PartitionType.MTK_DA_EMMC_PART_BOOT1 elif parttype == "boot2": parttype = PartitionType.MTK_DA_EMMC_PART_BOOT2 elif parttype == "gp1": parttype = PartitionType.MTK_DA_EMMC_PART_GP1 elif parttype == "gp2": parttype = PartitionType.MTK_DA_EMMC_PART_GP2 elif parttype == "gp3": parttype = PartitionType.MTK_DA_EMMC_PART_GP3 elif parttype == "gp4": parttype = PartitionType.MTK_DA_EMMC_PART_GP4 elif parttype == "rpmb": parttype = PartitionType.MTK_DA_EMMC_PART_RPMB self.check_usb_cmd() packetsize = 0x0 if self.daconfig.flashtype == "emmc": self.sdmmc_switch_part(parttype) packetsize = 0x100000 self.usbwrite(self.Cmd.READ_CMD) # D6 self.usbwrite(b"\x0C") # Host:Linux, 0x0B=Windows self.usbwrite(b"\x02") # Storage-Type: EMMC self.usbwrite(pack(">Q", addr)) self.usbwrite(pack(">Q", length)) self.usbwrite(pack(">I", packetsize)) ack = self.usbread(1)[0] if ack is not self.Rsp.ACK[0]: self.error( f"Error on sending read command, response: {hex(ack)}") exit(1) self.daconfig.readsize = self.daconfig.flashsize elif self.daconfig.flashtype == "nand": self.usbwrite(self.Cmd.NAND_READPAGE_CMD) # DF self.usbwrite(b"\x0C") # Host:Linux, 0x0B=Windows self.usbwrite(b"\x00") # Storage-Type: NUTL_READ_PAGE_SPARE self.usbwrite(b"\x01") # Addr-Type: NUTL_ADDR_LOGICAL self.usbwrite(pack(">I", addr)) self.usbwrite(pack(">I", length)) self.usbwrite(pack(">I", 0)) ack = self.usbread(1)[0] if ack is not self.Rsp.ACK: self.error( f"Error on sending read command, response: {hex(ack)}") exit(1) self.daconfig.pagesize = unpack(">I", self.usbread(4))[0] self.daconfig.sparesize = unpack(">I", self.usbread(4))[0] packetsize = unpack(">I", self.usbread(4))[0] pagestoread = 1 self.usbwrite(pack(">I", pagestoread)) self.usbread(4) self.daconfig.readsize = self.daconfig.flashsize // self.daconfig.pagesize * ( self.daconfig.pagesize + self.daconfig.sparesize) if display: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) old = 0 if filename != "": with open(filename, "wb") as wf: bytestoread = length while bytestoread > 0: size = bytestoread if bytestoread > packetsize: size = packetsize data = self.usbread(size, 0x400) wf.write(data) bytestoread -= size checksum = unpack(">H", self.usbread(2))[0] self.debug("Checksum: %04X" % checksum) self.usbwrite(self.Rsp.ACK) if display: prog = (length - bytestoread) / length * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex(length - bytestoread), bar_length=50) old = round(prog, 1) return True else: buffer = bytearray() bytestoread = length while bytestoread > 0: size = bytestoread if bytestoread > packetsize: size = packetsize buffer.extend(self.usbread(size, 0x400)) bytestoread -= size checksum = unpack(">H", self.usbread(2))[0] self.debug("Checksum: %04X" % checksum) self.usbwrite(self.Rsp.ACK) if display: prog = (length - bytestoread) / length * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete', bar_length=50) old = round(prog, 1) return buffer
def sdmmc_write_data(self, addr, length, filename, parttype=None, display=True): if parttype is None or parttype == "user": parttype = PartitionType.MTK_DA_EMMC_PART_USER elif parttype == "boot1": parttype = PartitionType.MTK_DA_EMMC_PART_BOOT1 elif parttype == "boot2": parttype = PartitionType.MTK_DA_EMMC_PART_BOOT2 elif parttype == "gp1": parttype = PartitionType.MTK_DA_EMMC_PART_GP1 elif parttype == "gp2": parttype = PartitionType.MTK_DA_EMMC_PART_GP2 elif parttype == "gp3": parttype = PartitionType.MTK_DA_EMMC_PART_GP3 elif parttype == "gp4": parttype = PartitionType.MTK_DA_EMMC_PART_GP4 elif parttype == "rpmb": parttype = PartitionType.MTK_DA_EMMC_PART_RPMB if self.daconfig.flashtype == "nor": storage = DaStorage.MTK_DA_STORAGE_NOR elif self.daconfig.flashtype == "nand": storage = DaStorage.MTK_DA_STORAGE_NAND elif self.daconfig.flashtype == "ufs": storage = DaStorage.MTK_DA_STORAGE_UFS elif self.daconfig.flashtype == "sdc": storage = DaStorage.MTK_DA_STORAGE_SDMMC else: storage = DaStorage.MTK_DA_STORAGE_EMMC if filename != "": with open(filename, "rb") as rf: if display: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) self.usbwrite(self.Cmd.SDMMC_WRITE_DATA_CMD) self.usbwrite(pack(">B", storage)) self.usbwrite(pack(">B", parttype)) self.usbwrite(pack(">Q", addr)) self.usbwrite(pack(">Q", length)) self.usbwrite(pack(">I", 0x100000)) if self.usbread(1) != self.Rsp.ACK: self.error("Couldn't send sdmmc_write_data header") return False offset = 0 old = 0 while offset < length: self.usbwrite(self.Rsp.ACK) count = min(0x100000, length - offset) data = bytearray(rf.read(count)) self.usbwrite(data) chksum = sum(data) & 0xFFFF self.usbwrite(pack(">H", chksum)) if self.usbread(1) != self.Rsp.CONT_CHAR: self.error("Data ack failed for sdmmc_write_data") return False if display: prog = offset / length * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex(offset), bar_length=50) old = round(prog, 1) offset += count if display: print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) return True
def readflash(self, type: int, start, length, display=False, filename: str = None): wf = None buffer = bytearray() if filename is not None: wf = open(filename, "wb") sectors = (length // 0x200) + (1 if length % 0x200 else 0) startsector = (start // 0x200) # emmc_switch(1) self.cdc.usbwrite(pack(">I", 0xf00dd00d)) self.cdc.usbwrite(pack(">I", 0x1002)) self.cdc.usbwrite(pack(">I", type)) if display: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) # kick-wdt # self.cdc.usbwrite(pack(">I", 0xf00dd00d)) # self.cdc.usbwrite(pack(">I", 0x3001)) bytestoread = sectors * 0x200 bytesread = 0 old = 0 # emmc_read(0) for sector in range(startsector, sectors): self.cdc.usbwrite(pack(">I", 0xf00dd00d)) self.cdc.usbwrite(pack(">I", 0x1000)) self.cdc.usbwrite(pack(">I", sector)) tmp = self.cdc.usbread(0x200, 0x200) if len(tmp) != 0x200: self.error("Error on getting data") return if display: prog = sector / sectors * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex((sectors * 0x200) - bytestoread), bar_length=50) old = round(prog, 1) bytesread += len(tmp) size = min(bytestoread, len(tmp)) if wf is not None: wf.write(tmp[:size]) else: buffer.extend(tmp) bytestoread -= size if display: print_progress(100, 100, prefix='Complete: ', suffix=filename, bar_length=50) if wf is not None: wf.close() else: return buffer[start % 0x200:(start % 0x200) + length]
def readflash(self, addr, length, filename, parttype=None, display=True): if parttype is None or parttype == "user": parttype = PartitionType.MTK_DA_EMMC_PART_USER elif parttype == "boot1": parttype = PartitionType.MTK_DA_EMMC_PART_BOOT1 if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.boot1_size) elif parttype == "boot2": parttype = PartitionType.MTK_DA_EMMC_PART_BOOT2 if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.boot2_size) elif parttype == "gp1": parttype = PartitionType.MTK_DA_EMMC_PART_GP1 if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.gp1_size) elif parttype == "gp2": parttype = PartitionType.MTK_DA_EMMC_PART_GP2 if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.gp2_size) elif parttype == "gp3": parttype = PartitionType.MTK_DA_EMMC_PART_GP3 if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.gp3_size) elif parttype == "gp4": parttype = PartitionType.MTK_DA_EMMC_PART_GP4 if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.gp4_size) elif parttype == "rpmb": parttype = PartitionType.MTK_DA_EMMC_PART_RPMB if self.daconfig.flashtype == "emmc": length = min(length, self.emmc.rpmb_size) else: self.error( "Unknown parttype. Known parttypes are \"boot1\",\"boot2\",\"gp1\"," + "\"gp2\",\"gp3\",\"gp4\",\"rpmb\"") return False if self.daconfig.flashtype == "nor": storage = DaStorage.MTK_DA_STORAGE_NOR elif self.daconfig.flashtype == "nand": storage = DaStorage.MTK_DA_STORAGE_NAND elif self.daconfig.flashtype == "ufs": storage = DaStorage.MTK_DA_STORAGE_UFS elif self.daconfig.flashtype == "sdc": storage = DaStorage.MTK_DA_STORAGE_SDMMC else: storage = DaStorage.MTK_DA_STORAGE_EMMC if self.cmd_read_data(addr=addr, size=length, storage=storage, parttype=parttype): if display: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) old = 0 bytestoread = length if filename != "": try: with open(filename, "wb") as wf: while bytestoread > 0: magic, datatype, slength = unpack( "<III", self.usbread(4 + 4 + 4)) tmp = self.usbread(slength, 512) bytestoread -= len(tmp) if display: prog = (length - bytestoread) / length * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex(length - bytestoread), bar_length=50) old = round(prog, 1) wf.write(tmp) self.ack() if self.status() != 0: break except Exception as err: self.error("Couldn't write to " + filename + ". Error: " + str(err)) return False if display: print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) return True else: buffer = bytearray() while length > 0: tmp = self.recv() buffer.extend(tmp) self.ack() if self.status() != 0: break if display: prog = (length - bytestoread) / length * 100 if round(prog, 1) > old: print_progress(prog, 100, prefix='Progress:', suffix='Complete, Sector:' + hex(length - bytestoread), bar_length=50) old = round(prog, 1) length -= len(tmp) if display: print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) return buffer return False
def read_memory(self, addr, bytestoread, display=False, wf=None): data = b"" old = 0 pos = 0 total = bytestoread if display: print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) while bytestoread > 0: if bytestoread > 0x080000: length = 0x080000 else: length = bytestoread bytesread = 0 try: self.cdc.read(1, 1) except Exception as e: # pylint: disable=broad-except self.debug(str(e)) pass if self.bit64: if not self.cdc.write( pack("<IIQQ", self.cmd.SAHARA_64BIT_MEMORY_READ, 0x8 + 8 + 8, addr + pos, length)): return None else: if not self.cdc.write( pack("<IIII", self.cmd.SAHARA_MEMORY_READ, 0x8 + 4 + 4, addr + pos, length)): return None while length > 0: try: tmp = self.cdc.read(length) except Exception as e: # pylint: disable=broad-except self.debug(str(e)) return None length -= len(tmp) pos += len(tmp) bytesread += len(tmp) if wf is not None: wf.write(tmp) else: data += tmp if display: prog = round(float(pos) / float(total) * float(100), 1) if prog > old: if display: print_progress(prog, 100, prefix='Progress:', suffix='Complete', bar_length=50) old = prog bytestoread -= bytesread if display: print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) ''' try: self.cdc.read(0) except: return data ''' return data