class CmdXmitState(CmdLoadELF): keywords = ["xmitstate"] description = "Sets a hook on a function, emmits an executable state and add the dump to frankenstein" parser = argparse.ArgumentParser(prog=keywords[0], description=description) parser.add_argument("target", help="Target function", type=auto_int) """ Receive state dump """ def xmit_state_hci_callback(self, record): hcipkt = record[0] if not issubclass(hcipkt.__class__, hci.HCI_Event): return #State report if hcipkt.event_code == 0xfc: saved_regs, cont = struct.unpack("II", hcipkt.data[:8]) if cont != 0: log.info("Receiving firmware state: regs@0x%x cont@0x%x" % (saved_regs, cont)) self.segment_data = [] self.segments = {} self.succsess = True self.saved_regs = saved_regs self.cont = cont else: if not self.succsess: return log.info("Received fuill firmware state") groupName = datetime.now().strftime("internalBlue_%m.%d.%Y_%H.%M.%S") self.project = Project("projects/"+self.internalblue.fw.FW_NAME) self.project.add_group(groupName) self.project.deactivate_all_groups() self.project.set_active_group(groupName, True) self.project.save() self.project.add_symbol(groupName, "cont", self.cont|1) self.project.add_symbol(groupName, "get_int", symbols["get_int"]) self.project.add_symbol(groupName, "set_int", symbols["set_int"]) self.project.add_symbol(groupName, "saved_regs", self.saved_regs) for segment_addr in self.segments: self.project.add_segment(groupName, "", segment_addr, "".join(self.segments[segment_addr])) self.project.save() if hcipkt.event_code == 0xfb: segment_addr,size,current = struct.unpack("III", hcipkt.data[:12]) self.segment_data += [hcipkt.data[12:]] #Check if we have missed an HCI event if segment_addr + len(self.segment_data)*128 != current + 128: if self.succsess: print( hex(segment_addr), hex(len(self.segment_data)*128), hex( current + 128)) log.info("Failed to receive state") self.succsess = False #Fully received memory dumo if len(self.segment_data)*128 == size: log.info("Received segment 0x%x - 0x%x" % (segment_addr, segment_addr+size)) self.segments[segment_addr] = self.segment_data self.segment_data = [] """ Command implementation """ def work(self): args = self.getArgs() if not args: return True # Initialize callbacks for xmitstate global CmdXmitStateInitialized if not CmdXmitStateInitialized: # disable uart_SetRTSMode if we know its location if self.internalblue.fw.FW_NAME == "CYW20735B1": self.internalblue.patchRom(0x3d32e, b"\x70\x47\x70\x47") elif self.internalblue.fw.FW_NAME == "CYW20819A1": self.internalblue.patchRom(0x2330e, b"\x70\x47\x70\x47") # and now let's enable the callbacks self.internalblue.registerHciCallback(self.debug_hci_callback) self.internalblue.registerHciCallback(self.xmit_state_hci_callback) CmdXmitStateInitialized = True patch = "projects/%s/gen/xmit_state.patch" % self.internalblue.fw.FW_NAME print(patch) if not os.path.exists(patch): log.warn("Could not find file %s" % patch) return False entry = self.load_ELF(patch) if entry == False: log.warn("Failed to load patch ELF %s" % patch) return False target = struct.pack("I", args.target | 1) self.writeMem(symbols["xmit_state_target"], target) self.launchRam(entry-1) return entry != False