def read_nvitem(self, item): rawdata = 128 * b'\x00' status = 0x0000 nvrequest = b'\x26' + write_object(nvitem_type, item, rawdata, status)['raw_data'] data = self.send(nvrequest) if len(data) == 0: data = self.send(nvrequest) if len(data) > 0: if data[0] == 0x26: res = read_object(data[1:], nvitem_type) name = "" if item in self.nvlist: name = self.nvlist[item] data = bytearray() for byte in res["rawdata"]: if byte == 0: break data.append(byte) res = nvitem(res["item"], data, res["status"], name) return [True, res] elif data[0] == 0x14: return [ False, f"Error 0x14 trying to read nvitem {hex(item)}." ] else: return [ False, f"Error {hex(data[0])} trying to read nvitem {hex(item)}." ] return [False, f"Empty request for nvitem {hex(item)}"]
def fromdata(self, data): tmp = read_object(data[0:0x9C], self.def_factory_header) self.magic1 = tmp["magic1"] self.magic2 = tmp["magic2"] self.fact_version = tmp["fact_version"] self.version = tmp["version"] self.block_size = tmp["block_size"] self.page_size = tmp["page_size"] self.block_count = tmp["block_count"] self.space_limit = tmp["space_limit"] self.upper_data = tmp["upper_data"]
def get_rsp(self): data = [] try: v = self.cdc.read() if v == b'': return [-1, -1] if b"<?xml" in v: return ["firehose", None] pkt = read_object(v[0:0x2 * 0x4], self.pkt_cmd_hdr) if "cmd" in pkt: cmd = pkt["cmd"] if cmd == self.cmd.SAHARA_HELLO_REQ: data = read_object(v[0x0:0xC * 0x4], self.pkt_hello_req) elif cmd == self.cmd.SAHARA_DONE_RSP: data = read_object(v[0x0:0x3 * 4], self.pkt_done) elif cmd == self.cmd.SAHARA_END_TRANSFER: data = read_object(v[0x8:0x8 + 0x2 * 0x4], self.pkt_image_end) elif cmd == self.cmd.SAHARA_64BIT_MEMORY_READ_DATA: self.bit64 = True data = read_object(v[0x8:0x8 + 0x3 * 0x8], self.pkt_read_data_64) elif cmd == self.cmd.SAHARA_READ_DATA: self.bit64 = False data = read_object(v[0x8:0x8 + 0x3 * 0x4], self.pkt_read_data) elif cmd == self.cmd.SAHARA_64BIT_MEMORY_DEBUG: self.bit64 = True data = read_object(v[0x8:0x8 + 0x2 * 0x8], self.pkt_memory_debug_64) elif cmd == self.cmd.SAHARA_MEMORY_DEBUG: self.bit64 = False data = read_object(v[0x8:0x8 + 0x2 * 0x4], self.pkt_memory_debug) elif cmd == self.cmd.SAHARA_EXECUTE_RSP: data = read_object(v[0:0x4 * 0x4], self.pkt_execute_rsp_cmd) elif cmd == self.cmd.SAHARA_CMD_READY or cmd == self.cmd.SAHARA_RESET_RSP: data = [] else: return None return [pkt, data] except Exception as e: # pylint: disable=broad-except self.error(str(e)) return None
def parse_da_loader(self, loader): try: with open(loader, 'rb') as bootldr: data = bootldr.read() self.debug(hexlify(data).decode('utf-8')) bootldr.seek(0x68) count_da = unpack("<I", bootldr.read(4))[0] for i in range(0, count_da): bootldr.seek(0x6C + (i * 0xDC)) datmp = read_object(bootldr.read(0x14), DA) # hdr datmp["loader"] = loader da = [datmp] # bootldr.seek(0x6C + (i * 0xDC) + 0x14) #sections count = datmp["entry_region_count"] for m in range(0, count): entry_tmp = read_object(bootldr.read(20), entry_region) da.append(entry_tmp) self.dasetup.append(da) return True except Exception as e: self.error("Couldn't open loader: " + loader + ". Reason: " + str(e)) return False
def read_nvitemsub(self, item, index): rawdata = 128 * b'\x00' status = 0x0000 nvrequest = b'\x4B\x30\x01\x00' + write_object(subnvitem_type, item, index, rawdata, status)['raw_data'] data = self.send(nvrequest) if len(data) == 0: data = self.send(nvrequest) if len(data) > 0: if data[0] == 0x4B: res = read_object(data[4:], subnvitem_type) name = "" if item in self.nvlist: name = self.nvlist[item] data=self.unpackdata(res["rawdata"]) res = nvitem(res["item"], index, data, res["status"], name) return [True, res] elif data[0] == 0x14: return [False, f"Error 0x14 trying to read nvitem {hex(item)}."] else: return [False, f"Error {hex(data[0])} trying to read nvitem {hex(item)}."] return [False, f"Empty request for nvitem {hex(item)}"]
def read_flash_info(self): data = self.usbread(0x1C) self.nor = read_object(data, norinfo) data = self.usbread(0x11) self.nand = read_object(data, nandinfo64) nandcount = self.nand["m_nand_flash_id_count"] if nandcount == 0: self.nand = read_object(data, nandinfo32) nandcount = self.nand["m_nand_flash_id_count"] nc = data[-4:] + self.usbread(nandcount * 2 - 4) else: nc = self.usbread(nandcount * 2) m_nand_dev_code = unpack(">" + str(nandcount) + "H", nc) self.nand["m_nand_flash_dev_code"] = m_nand_dev_code ni2 = read_object(self.usbread(9), nandinfo2) for ni in ni2: self.nand[ni] = ni2[ni] self.emmc = read_object(self.usbread(0x5C), emmcinfo) self.sdc = read_object(self.usbread(0x1C), sdcinfo) self.flashconfig = read_object(self.usbread(0x26), configinfo) pi = read_object(self.usbread(0xA), passinfo) if pi["ack"] == 0x5A: return True return False
def fromdata(self, data): tmp = read_object(data[0:0x10], self.def_fs_factimage_read_info) self.stream_state = tmp["stream_state"] self.info_cluster_sent = tmp["info_cluster_sent"] self.cluster_map_seqno = tmp["cluster_map_seqno"] self.cluster_data_seqno = tmp["cluster_data_seqno"]
def debug_mode(self): if not self.cmd_hello(self.sahara_mode.SAHARA_MODE_MEMORY_DEBUG): return False if os.path.exists("memory"): rmrf("memory") os.mkdir("memory") cmd, pkt = self.get_rsp() if cmd["cmd"] == self.cmd.SAHARA_MEMORY_DEBUG or cmd[ "cmd"] == self.cmd.SAHARA_64BIT_MEMORY_DEBUG: memory_table_addr = pkt["memory_table_addr"] memory_table_length = pkt["memory_table_length"] if self.bit64: pktsize = 8 + 8 + 8 + 20 + 20 if memory_table_length % pktsize == 0: if memory_table_length != 0: print( f"Reading 64-Bit partition from {hex(memory_table_addr)} with length of " + "{hex(memory_table_length)}") ptbldata = self.read_memory(memory_table_addr, memory_table_length) num_entries = len(ptbldata) // pktsize partitions = [] for id_entry in range(0, num_entries): pd = read_object( ptbldata[id_entry * pktsize:(id_entry * pktsize) + pktsize], self.parttbl_64bit) desc = pd["desc"].replace(b"\x00", b"").decode('utf-8') filename = pd["filename"].replace( b"\x00", b"").decode('utf-8') mem_base = pd["mem_base"] save_pref = pd["save_pref"] length = pd["length"] partitions.append( dict(desc=desc, filename=filename, mem_base=mem_base, length=length, save_pref=save_pref)) print( f"{filename}({desc}): Offset {hex(mem_base)}, Length {hex(length)}, " + "SavePref {hex(save_pref)}") self.dump_partitions(partitions) return True return True else: pktsize = (4 + 4 + 4 + 20 + 20) if memory_table_length % pktsize == 0: if memory_table_length != 0: print( f"Reading 32-Bit partition from {hex(memory_table_addr)} " + f"with length of {hex(memory_table_length)}") ptbldata = self.read_memory(memory_table_addr, memory_table_length) num_entries = len(ptbldata) // pktsize partitions = [] for id_entry in range(0, num_entries): pd = read_object( ptbldata[id_entry * pktsize:(id_entry * pktsize) + pktsize], self.parttbl) desc = pd["desc"].replace(b"\x00", b"").decode('utf-8') filename = pd["filename"].replace( b"\x00", b"").decode('utf-8') mem_base = pd["mem_base"] save_pref = pd["save_pref"] length = pd["length"] partitions.append( dict(desc=desc, filename=filename, mem_base=mem_base, length=length, save_pref=save_pref)) print( f"{filename}({desc}): Offset {hex(mem_base)}, " + f"Length {hex(length)}, SavePref {hex(save_pref)}" ) self.dump_partitions(partitions) return True elif "status" in pkt: self.error(self.get_error_desc(pkt["status"])) return False return False
def connect(self): try: v = self.cdc.read() if len(v) > 1: if v[0] == 0x01: cmd = read_object(v[0:0x2 * 0x4], self.pkt_cmd_hdr) if cmd['cmd'] == self.cmd.SAHARA_HELLO_REQ: data = read_object(v[0x0:0xC * 0x4], self.pkt_hello_req) self.pktsize = data['max_cmd_len'] self.version = float( str(data['version']) + "." + str(data['version_min'])) return ["sahara", data] elif v[0] == self.cmd.SAHARA_END_TRANSFER: return ["sahara", None] elif b"<?xml" in v: return ["firehose", None] elif v[0] == 0x7E: return ["nandprg", None] else: data = b"<?xml version=\"1.0\" ?><data><nop /></data>" self.cdc.write(data, 0x80) res = self.cdc.read() if res == b"": try: data = b"\x7E\x06\x4E\x95\x7E" # Streaming nop self.cdc.write(data, 0x80) res = self.cdc.read() if b"\x7E\x0D\x16\x00\x00\x00\x00" in res or b"Invalid Command" in res: return ["nandprg", None] else: return ["", None] except Exception as e: # pylint: disable=broad-except self.error(str(e)) return ["", None] if b"<?xml" in res: return ["firehose", None] elif len(res) > 0 and res[0] == self.cmd.SAHARA_END_TRANSFER: print( "Device is in Sahara error state, please reboot the device." ) return ["sahara", None] else: data = b"\x7E\x11\x00\x12\x00\xA0\xE3\x00\x00\xC1\xE5\x01\x40\xA0\xE3\x1E\xFF\x2F\xE1\x4B\xD9\x7E" self.cdc.write(data, 0x80) res = self.cdc.read() if len(res) > 0 and res[1] == 0x12: return ["nandprg", None] else: self.cmd_modeswitch( self.sahara_mode.SAHARA_MODE_COMMAND) return ["sahara", None] except Exception as e: # pylint: disable=broad-except self.error(str(e)) self.cmd_modeswitch(self.sahara_mode.SAHARA_MODE_MEMORY_DEBUG) cmd, pkt = self.get_rsp() if cmd == -1 and pkt == -1: return ["", None] return ["sahara", pkt]