def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-daemon {} - Collaborative board access daemon\n".format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) helper.add_file_handling_opts(parser) helper.add_resetseq_options(parser, resets) parser.add_argument("-L", "--listen", help="Specify address:port to listen (default 0.0.0.0:10000)", nargs=1, metavar=('listen'), default=["0.0.0.0:10000"], required=False) opts = parser.parse_args() chip, term, reset = helper.create_core_stuff_from_options(opts) c = helper.detect_chip_type(opts, chips, formats) if opts.log: term.logstream = opts.log srv = server(term, opts.listen[0]) srv.set_reset_seq(reset) if "file" in opts: srv.preload_binaries(opts.file) return srv.loop()
def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-daemon {} - Collaborative board access daemon\n". format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) helper.add_file_handling_opts(parser) helper.add_resetseq_options(parser, resets) parser.add_argument( "-L", "--listen", help="Specify address:port to listen (default 0.0.0.0:10000)", nargs=1, metavar=('listen'), default=["0.0.0.0:10000"], required=False) parser.add_argument( "-m", "--max-usage-time", help= "Specify maximum time a client can use the board before being kicked (seconds)", default=360, type=int, required=False) parser.add_argument( "--execute-binaries-from-temp-dir", help= "Super-special debug mode. Mock a bootrom, receive upload binaries and exec them", action="store_true", required=False) opts = parser.parse_args() if opts.execute_binaries_from_temp_dir: opts.port = "loop://" chip, term, reset = helper.create_core_stuff_from_options(opts) c = helper.detect_chip_type(opts, chips, formats) if opts.log: term.logstream = opts.log srv = server(term, opts.listen[0], opts.max_usage_time, opts.execute_binaries_from_temp_dir) srv.set_reset_seq(reset) if "file" in opts: srv.preload_binaries(opts.file) return srv.loop()
def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-daemon {} - Collaborative board access daemon\n". format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) helper.add_file_handling_opts(parser) helper.add_resetseq_options(parser, resets) parser.add_argument( "-L", "--listen", help="Specify address:port to listen (default 0.0.0.0:10000)", nargs=1, metavar=('listen'), default=["0.0.0.0:10000"], required=False) opts = parser.parse_args() c = helper.detect_chip_type(opts, chips, formats) if c == None: c = chips["basis"] return 1 print("Detected chip: %s (%s)" % (c.name, c.part)) if c == None: print("ERROR: Failed to auto-detect chip type") return 1 if opts.baud == None: opts.baud = [c.baudrate] reset = resets[opts.reset[0]](opts) if opts.log: term.logstream = opts.log print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Serial Port: %s" % opts.port[0]) print("Listen address: %s" % opts.listen) term = terminal(opts.port[0], opts.baud[0]) srv = server(term, opts.listen[0]) srv.set_reset_seq(reset) if "file" in opts: srv.preload_binaries(opts.file) return srv.loop()
def __init__(self, target_chip=None, transport="xmodem", args=None): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") c = chips[target_chip] parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description= "Rumboot Scripting Engine script, using rumboot-tools {}\n".format( rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) helper.add_resetseq_options(parser, resets) opts = parser.parse_args() dump_path = os.path.dirname(__file__) + "/romdumps/" helper.detect_terminal_options(opts, c) print("Target Chip: %s (%s)" % (c.name, c.part)) if c == None: raise Exception("ERROR: Failed to auto-detect chip type") if opts.baud == None: opts.baud = [c.baudrate] reset = resets[opts.reset[0]](opts) term = terminal(opts.port[0], opts.baud[0]) term.set_chip(c) try: romdump = open(dump_path + c.romdump, "r") term.add_dumps({'rom': romdump}) except: pass if opts.log: term.logstream = opts.log print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Port: %s" % opts.port[0]) if opts.edcl and c.edcl != None: term.xfer.selectTransport("edcl") print("Preferred data transport: %s" % term.xfer.how) print("--- --- --- --- --- --- --- --- --- ") self.terminal = term self.xfer = term.xfer
def intialize_testing(target_chip=None): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") c = chips[target_chip] parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-factorytest {} - RumBoot Board Testing Framework\n" .format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) helper.add_resetseq_options(parser, resets) opts = parser.parse_args() dump_path = os.path.dirname(__file__) + "/romdumps/" helper.detect_terminal_options(opts, c) print("Detected chip: %s (%s)" % (c.name, c.part)) if c == None: print("ERROR: Failed to auto-detect chip type") return 1 if opts.baud == None: opts.baud = [c.baudrate] reset = resets[opts.reset[0]](opts) term = terminal(opts.port[0], opts.baud[0]) term.set_chip(c) try: romdump = open(dump_path + c.romdump, "r") term.add_dumps({'rom': romdump}) except: pass if opts.log: term.logstream = opts.log print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Port: %s" % opts.port[0]) if opts.edcl and c.edcl != None: term.xfer.selectTransport("edcl") print("Preferred data transport: %s" % term.xfer.how) print("--- --- --- --- --- --- ") return term, reset
def create_core_stuff_from_options(self, opts): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") c = self.detect_chip_type(opts, chips, formats) if not c: return None, None, None print("Detected chip: %s (%s)" % (c.name, c.part)) if c == None: raise Exception("ERROR: Failed to auto-detect chip type") if opts.baud == None: opts.baud = c.baudrate params_for_xfers = { "force_static_arp": opts.force_static_arp, "default": "xmodem" } if opts.edcl: params_for_xfers["default"] = "edcl" if opts.edcl_ip: params_for_xfers["edcl_ip"] = opts.edcl_ip if opts.edcl_mac: params_for_xfers["edcl_mac"] = opts.edcl_mac if opts.edcl_timeout: params_for_xfers["edcl_timeout"] = opts.edcl_timeout term = terminal(opts.port, opts.baud, xferparams=params_for_xfers) reset = resets[opts.reset[0]](term, vars(opts)) term.set_chip(c) reset.set_chip(c) print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud)) print("Port: %s" % opts.port) print("Preferred data transport: %s" % params_for_xfers["default"]) return c, term, reset
def __init__(self): self.opts = None self.env = {} self.resets = ResetSeqFactory("rumboot.resetseq") self.chips = ChipDb("rumboot.chips") self.chip = None
def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-gdb {} - Debugger launcher tool\n".format( rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) parser.add_argument( "-v", "--verbose", action='store_true', default=False, help="Print serial debug messages during preload phase"), parser.add_argument("-z", "--spl-path", help="Path for SPL writers (Debug only)", type=str, required=False) parser.add_argument("-L", "--load", help="Load binary on start", action='store_true', default=False, required=False) parser.add_argument("-f", "--file", help="Application ELF file to debug", type=str, required=False) parser.add_argument( "-x", "--exec", help="Execute supplied binary on start (Implies --load)", action='store_true', default=False, required=False) parser.add_argument("-R", "--rebuild", help="Attempt to rebuild binary", action='store_true', default=False, required=False) parser.add_argument("--debug-remote", help="Send 'set debug remote 1' to gdb for debugging", action='store_true', default=False, required=False) parser.add_argument("--debug-serial", help="Send 'set debug serial 1' to gdb for debugging", action='store_true', default=False, required=False) parser.add_argument("-g", "--gdb-path", help="Path to flashrom binary", type=str, required=False) parser.add_argument("-G", "--gdb-gui", help="Start GDB gui", action='store_true', default=False, required=False) parser.add_argument("-c", "--chip_id", help="Chip Id (numeric or name)", required=True) parser.add_argument('remaining', nargs=argparse.REMAINDER, default=[], help="Extra gdb arguments (e.g. filename)") helper.add_resetseq_options(parser, resets) opts = parser.parse_args() if opts.remaining and opts.remaining[0] == "--": opts.remaining = opts.remaining[1:] gdb_args = " ".join(opts.remaining) c = chips[opts.chip_id] if (c == None): return 1 helper.detect_terminal_options(opts, c) print("Detected chip: %s (%s)" % (c.name, c.part)) if c.warning != None: print(" --- WARNING ---") print(c.warning) print(" --- WARNING ---") print("") spl_path = os.path.dirname(__file__) + "/tools/" if opts.baud == None: opts.baud = [c.baudrate] reset = resets[opts.reset[0]](opts) term = terminal(opts.port[0], opts.baud[0]) term.verbose = opts.verbose term.set_chip(c) if opts.log: term.logstream = opts.log try: spl = c.stub except: print("ERROR: Target chip (%s) doesn't have a gdb stub" % (c.name)) return 1 if opts.spl_path != None: spl_path = opts.spl_path print("SPL %s" % (spl_path + c.stub)) spl = spl_path + c.stub if opts.gdb_path: gdb = opts.gdb_path else: gdb = c.gdb print(opts.rebuild, opts.file) if opts.rebuild and opts.file != None: if 0 != os.system("cmake --build . --target " + opts.file): os.exit(1) print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Port: %s" % opts.port[0]) print("GDB: %s" % gdb) if opts.edcl and c.edcl != None: term.xfer.selectTransport("edcl") reset.resetToHost() term.add_binaries(spl) term.loop(break_after_uploads=True) while True: s = term.ser.readline() if opts.verbose: print(s) if s.decode("utf-8", errors="replace").find("STUB READY!") != -1: break print("gdb-stub is ready for operations, starting gdb..") # If we're here, we'll need to setup socket redirector port = 20000 while True: try: print("Trying port %d" % port) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(("127.0.0.1", port)) server.listen() break except: port = port + 1 if port > 30000: print("Weird shit going on, breaking") break #Fire up flashrom in background if opts.gdb_gui: flr = ipgdbgui() else: flr = ipgdb() if opts.debug_remote: flr.add_command("set debug remote 1") if opts.debug_serial: flr.add_command("set debug serial 1") if opts.file != None: gdb_args = gdb_args + opts.file flr.configure(gdb, port, gdb_args) if opts.load or opts.exec: flr.add_command("load") if opts.exec: flr.add_command("continue") flr.start() #Accept connection connection, client_address = server.accept() connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) rd = redirector() rd.configure(term.ser, connection) rd.start() return flr.join()
def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-xrun {} - RumBoot X-Modem execution tool\n".format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_file_handling_opts(parser, True) helper.add_terminal_opts(parser) helper.add_resetseq_options(parser, resets) plus = parser.add_argument_group("Plusargs parser options", """ rumboot-xrun can parse plusargs (similar to verilog simulator) and use them for runtime file uploads. This option is intended to be used for """) plus.add_argument('-A', '--plusargs', nargs='*') parser.add_argument("-R", "--rebuild", help="Attempt to rebuild/update target before uploading", action="store_true", default=False, required=False) parser.add_argument("-I", '--stdin', help="Use stdin redirection to tty", action="store_true", default=False, required=False) parser.add_argument('--replay-no-exit', help="Do not exit on panics/rom returns when replaying logs (for batch analysis)", action="store_true", default=False, required=False) if len(sys.argv) == 1: sys.argv = sys.argv + ["--help"] opts = parser.parse_args() #Open files, rebuild if needed opts.file[0], dumps = helper.process_files(opts.file[0], opts.rebuild) dump_path = os.path.dirname(__file__) + "/romdumps/" plusargs = {} if opts.plusargs: for a in opts.plusargs: ret = parse("+{}={}", a) if ret: plusargs[ret[0]] = ret[1] continue ret = parse("+{}", a) if ret: plusargs[ret[0]] = True c = helper.detect_chip_type(opts, chips, formats) if c == None: return 1 print("Detected chip: %s (%s)" % (c.name, c.part)) if c == None: print("ERROR: Failed to auto-detect chip type") return 1 if opts.baud == None: opts.baud = [ c.baudrate ] reset = resets[opts.reset[0]](opts) term = terminal(opts.port[0], opts.baud[0]) term.set_chip(c) term.plusargs = plusargs term.xfer.xfers["edcl"].force_static_arp = opts.force_static_arp try: romdump = open(dump_path + c.romdump, "r") term.add_dumps({'rom' : romdump}) except: pass if opts.log: term.logstream = opts.log print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Port: %s" % opts.port[0]) reset.resetToHost() term.add_binaries(opts.file) term.add_dumps(dumps) term.replay_till_the_end = opts.replay_no_exit if opts.edcl and c.edcl != None: term.xfer.selectTransport("edcl") print("Preferred data transport: %s" % term.xfer.how) return term.loop(opts.stdin)
def rumboot_start_flashing(partmap=None): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-xflash {} - RumBoot firmware updater tool\n". format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_file_handling_opts(parser, True) helper.add_terminal_opts(parser) parser.add_argument("-v", "--verbose", default=False, action='store_true', help="Print serial debug messages during update"), parser.add_argument("-m", "--memory", help="Memory program. Help for a list of memories", metavar=('memory'), default="help") parser.add_argument("-z", "--spl-path", help="Path for SPL writers (Debug only)", type=str, required=False) parser.add_argument( "--no-spl", help="Do not upload spl, assume it boots on it's own (Debug only)", action="store_true", default=False, required=False) parser.add_argument("-o", "--offset", help="Memory offset for read/write operations", type=int, default=0, required=False) parser.add_argument( "-L", "--length", help="How many bytes to read/write (defaults to whole file/flash)", type=int, default=-1, required=False) parser.add_argument("-R", "--read", help="Read flash to file", action='store_true', required=False) parser.add_argument("-W", "--write", help="Write flash from file", default=False, action='store_true', required=False) parser.add_argument("-E", "--erase", help="Erase flash", default=False, action='store_true', required=False) parser.add_argument("-F", "--firmware-file", help="Write firmware from configuration file", type=argparse.FileType("r"), default=None, required=False) parser.add_argument("-U", "--upload-baudrate", help="Change baudrate for uploads", default=0, type=int, required=False) helper.add_resetseq_options(parser, resets) opts = parser.parse_args() chip = helper.detect_chip_type(opts, chips, formats) if not chip: return 1 mem = opts.memory if mem == "help": print(f"Available memories for chip '{chip.name}'") for mem, cfg in chip.memories.items(): print("%16s: %s" % (mem, cfg["comment"])) return 1 chip, term, reset = helper.create_core_stuff_from_options(opts) if opts.read and opts.write: print("Please select either --read or --write, not both") return 1 #Open files, rebuild if needed #opts.file[0], dumps = helper.process_files(opts.file[0], False) spl_path = os.path.dirname(__file__) + "/spl-tools/" try: config = chip.memories[mem] mem = config["device"] except: print( "ERROR: Target chip (%s) doesn't have memory '%s'. Run with -m help for a list" % (chip.name, mem)) return 1 if opts.spl_path != None: spl_path = opts.spl_path print("SPL %s" % (spl_path + chip.memories[mem])) spl = spl_path + config["spl"] term.verbose = opts.verbose if not opts.no_spl: term.add_binaries(spl) if opts.edcl and chip.edcl != None: term.xfer.selectTransport("edcl") try: reset.resetToHost() except: print("WARN: Reset method doesn't support HOST mode switching") print("WARN: If things don't work - check jumpers!") reset.reset() term.loop(break_after_uploads=True) flashers = FlashAlgoFactory("rumboot.flashing", config["protocol"]) flasher = flashers[mem](term, config) # ------------------------ offset = opts.offset length = -1 if "offset" in config: offset += config["offset"] if "size" in config: flasher.size = config["size"] flasher.dump() if opts.file and len(opts.file) > 1: print("ERROR: Only one file may be specified") return 1 if opts.file and len(opts.file) == 0: return 1 if opts.upload_baudrate == 0 and hasattr(chip, "flashbaudrate"): opts.upload_baudrate = chip.flashbaudrate if opts.upload_baudrate > 0: print(f"WARN: Changing baudrate to {opts.upload_baudrate} bps") print( "WARN: If everything freezes - try a different setting via -U / --upload-baudrate" ) flasher.switchbaud(opts.upload_baudrate) term.xfer.connect(chip) runlist = [] if opts.firmware_file is None: part = flasher.add_partition(mem, opts.offset, opts.length) if opts.write: action = { "partition": part, "action": "write", "file": opts.file[0][0] } runlist.append(action) if opts.read: action = { "partition": part, "action": "read", "file": opts.file[0][0] } runlist.append(action) if opts.erase: action = {"partition": part, "action": "erase", "file": None} runlist.append(action) else: runlist = parse_firmware_file(opts.firmware_file, flasher) execute_runlist(term, spl, runlist) if opts.firmware_file or opts.write: print("Saving environment and partition information") flasher.save_partitions() flasher.saveenv() return 1
def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-flashrom {} - flashrom wrapper tool\n".format( rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_terminal_opts(parser) parser.add_argument( "-v", "--verbose", action='store_true', default=False, help="Print serial debug messages during preload phase"), parser.add_argument( "-m", "--memory", help="SPI bus to use. Names match '-m help' of rumboot-xflash", nargs=1, metavar=('memory'), default="help", required=True) parser.add_argument("-z", "--spl-path", help="Path for SPL writers (Debug only)", type=str, required=False) parser.add_argument("-f", "--flashrom-path", help="Path to flashrom binary", type=str, required=False) parser.add_argument("-c", "--chip_id", help="Chip Id (numeric or name)", required=True) parser.add_argument('remaining', nargs=argparse.REMAINDER, default=[], help="Flashrom arguments") # parser.add_argument('-F', '--flashrom-args', nargs='*', default=[], ) helper.add_resetseq_options(parser, resets) opts = parser.parse_args() if opts.remaining and opts.remaining[0] == "--": opts.remaining = opts.remaining[1:] flashrom_args = " ".join(opts.remaining) c = chips[opts.chip_id] if (c == None): return 1 helper.detect_terminal_options(opts, c) print("Detected chip: %s (%s)" % (c.name, c.part)) if c.warning != None: print(" --- WARNING ---") print(c.warning) print(" --- WARNING ---") print("") spl_path = os.path.dirname(__file__) + "/tools/" if opts.baud == None: opts.baud = [c.baudrate] reset = resets[opts.reset[0]](opts) term = terminal(opts.port[0], opts.baud[0]) term.verbose = opts.verbose term.set_chip(c) if opts.log: term.logstream = opts.log mem = opts.memory[0] if not mem: return 1 if mem == "help": for mem, spl in c.flashrom.items(): print("Memory %16s: %s" % (mem, spl)) return 1 try: spl = c.flashrom[mem] except: print( "ERROR: Target chip (%s) doesn't have bus '%s'. Run with -m help for a list" % (c.name, mem)) return 1 if opts.spl_path != None: spl_path = opts.spl_path print("SPL %s" % (spl_path + c.flashrom[mem])) spl = spl_path + c.flashrom[mem] print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Port: %s" % opts.port[0]) flashrom = None flashrom_paths = [ "/usr/local/sbin/flashrom", "/sbin/flashrom", "/usr/sbin/flashrom", "C:\\flashrom\\flashrom.exe" ] if opts.flashrom_path and os.path.exists(opts.flashrom_path): flashrom = opts.flashrom_path elif opts.flashrom_path: print("[W] Specified flashrom path (%s) is invalid, trying to guess" % opts.flashrom_path) for f in flashrom_paths: if os.path.exists(f): flashrom = f if flashrom == None: print( "FATAL: Failed to find working flashrom. Please download and install from https://flashrom.org/" ) return 1 print("FlashRom: %s" % flashrom) print("FlashRom args: %s" % flashrom_args) reset.resetToHost() term.add_binaries(spl) term.loop(break_after_uploads=True) while True: s = term.ser.readline() if s.decode("utf-8", errors="replace").find("SERPROG READY!") != -1: break print("Serprog stub ready!") if opts.port[0].find("socket://") == -1: #Use flashrom directly ret = os.system(flashrom + " -p serprog:dev=" + opts.port[0] + ":" + opts.baud[0]) reset.resetToNormal return ret # If we're here, we'll need to setup socket redirector port = 20000 while True: try: print("Trying port %d" % port) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(("127.0.0.1", port)) server.listen() break except: port = port + 1 if port > 30000: print("Weird shit going on, breaking") break #Fire up flashrom in background flr = ipflashrom() flr.configure(flashrom, port, flashrom_args) flr.start() #Accept connection connection, client_address = server.accept() connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) rd = redirector() rd.configure(term.ser, connection) rd.start() return flr.join()
class edclmanager(object): edcl = None verbose = False chips = ChipDb("rumboot.chips") warned = [] force_static_arp = False def __init__(self): self.edcl = edcl() def check_reachability(self, ip): for i in ni.interfaces(): if not ni.AF_INET in ni.ifaddresses(i): continue for addr in ni.ifaddresses(i)[ni.AF_INET]: if IPAddress(ip) in IPNetwork(addr['addr'] + "/" +addr["netmask"]): return True return False def buggy_ip(self, params): arr = params["ip"].split(".") return int(arr[3]) == 0 def __getattribute__(self, key): try: return object.__getattribute__(self, key) except: return object.__getattribute__(self.edcl, key) def try_connect(self, chip, params): if self.buggy_ip(params) or self.force_static_arp: #FIXME: This logic sucks. #TODO: Implement a better solution to find non-used IP on the subnet params["ip"] = params["ip"].replace(".0", ".76") self.prepareStaticARP(chip, params) if not self.check_reachability(params["ip"]) and not params["ip"] in self.warned: print("WARNING: IP address %s is not in your subnet." % params["ip"]) print("WARNING: Please check network interface settings.") self.warned.append(params["ip"]) return None if self.verbose: print("Testing: %s (%s) IP %s" % (chip.__name__, params["name"], params["ip"])) try: ret = self.edcl.connect(params["ip"]) except: return None if ret: print("Connected: %s (%s)" % (chip.__name__, params["name"])) return chip def probe(self, chip): for params in chip.edcl: if None != self.try_connect(chip, params): return params return None def scan(self, match=None): ret = [] if type(match) == int or type(match) == str: match = self.chips[match] if match == None: chips = self.chips else: chips = { match } for c in chips: tmp = self.probe(c) if tmp != None: db = { "chip" : c, "params": tmp } ret.append(db) return ret def test_chip(self, chip): pass def showArpWarning(self, cmd): print("WARNING: Trying to add ARP record via 'sudo'/'runas'.") print("WARNING: If that doesn't work please run manually: %s" % cmd) def dropARP(self, chip, params): if platform.system() == 'Linux': cmd = "sudo arp -d %s" % params["ip"] elif platform.system() == 'Windows': cmd = "runas /user:Administrator arp /d %s" % params["ip"] else: raise("FATAL: Don't know how to add static ARP on %s", platform.system()) os.system(cmd) self.showArpWarning(cmd) def addARP(self, chip, params): if platform.system() == 'Linux': cmd = "sudo arp -s %s %s" % (params["ip"], params["mac"]) elif platform.system() == 'Windows': cmd = "runas /user:Administrator arp /s %s %s" % (params["ip"], params["mac"].upper().replace(":","-")) else: raise("FATAL: Don't know how to add static ARP on %s", platform.system()) os.system(cmd) self.showArpWarning(cmd) def listARP(self): ret = {} if platform.system() == 'Linux': cmd = "/usr/sbin/arp -n" elif platform.system() == 'Windows': cmd = "arp -a" else: raise("FATAL: I don't know how to query ARP on %s", platform.system()) out = subprocess.Popen(cmd.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout,stderr = out.communicate() if platform.system() == 'Linux': for l in stdout.decode().split("\n"): result = parse("{:<} ether {:>} {:>} {:>}", l) if result == None: continue ret[result[0]]=result[1] elif platform.system() == 'Windows': for l in stdout.decode().split("\n"): result = parse("{:<} {:>} {:>}", l) if result == None: continue ret[result[0]]=result[1].replace("-",":") return ret def getARP(self, ip): tbl = self.listARP() if ip in tbl: return tbl[ip] def prepareStaticARP(self, chip, params): if self.getARP(params["ip"]) and not self.force_static_arp: print("Static ARP record already exists, good") return if self.force_static_arp: self.dropARP(chip, params) self.addARP(chip, params) def smartupload(self, address, image, callback = None): self.edcl.send_from_file(address + 4, image, callback, 4) self.edcl.send_from_file(address , image, None, 0, 4) def connect(self, chip): for i in range(3): ret = self.scan(chip) if ret != []: return ret
def smoke_test(): db = ChipDb("rumboot.chips") c = db["basis"] assert c.chip_id == 3 assert c.chip_rev == 1
def test_chipdb(): db = ChipDb("rumboot.chips") c = db["basis"] assert c.chip_id == 3 assert c.chip_rev == 1
def cli(): resets = ResetSeqFactory("rumboot.resetseq") formats = ImageFormatDb("rumboot.images") chips = ChipDb("rumboot.chips") parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="rumboot-xflash {} - RumBoot X-Modem firmware update tool\n" .format(rumboot.__version__) + rumboot.__copyright__) helper = arghelper() helper.add_file_handling_opts(parser, True) helper.add_terminal_opts(parser) parser.add_argument("-v", "--verbose", action='store_true', help="Print serial debug messages during update"), parser.add_argument("-m", "--memory", help="Memory program. Help for a list of memories", nargs=1, metavar=('memory'), default="help", required=True) parser.add_argument("-z", "--spl-path", help="Path for SPL writers (Debug only)", type=str, required=False) helper.add_resetseq_options(parser, resets) opts = parser.parse_args() c = helper.detect_chip_type(opts, chips, formats) if (c == None): return 1 mem = opts.memory[0] if not mem: return 1 if mem == "help": for mem, spl in c.memories.items(): print("Memory %16s: %s" % (mem, spl)) return 1 #Open files, rebuild if needed opts.file[0], dumps = helper.process_files(opts.file[0], False) print("Detected chip: %s (%s)" % (c.name, c.part)) if c.warning != None: print(" --- WARNING ---") print(c.warning) print(" --- WARNING ---") print("") spl_path = os.path.dirname(__file__) + "/spl-tools/" if opts.baud == None: opts.baud = [c.baudrate] reset = resets[opts.reset[0]](opts) term = terminal(opts.port[0], opts.baud[0]) term.set_chip(c) if opts.log: term.logstream = opts.log term.verbose = opts.verbose term.xfer.xfers["edcl"].force_static_arp = opts.force_static_arp try: spl = c.memories[mem] except: print( "ERROR: Target chip (%s) doesn't have memory '%s'. Run with -m help for a list" % (c.name, mem)) return 1 if opts.spl_path != None: spl_path = opts.spl_path print("SPL %s" % (spl_path + c.memories[mem])) spl = spl_path + c.memories[mem] print("Reset method: %s" % (reset.name)) print("Baudrate: %d bps" % int(opts.baud[0])) print("Port: %s" % opts.port[0]) reset.resetToHost() term.add_binaries(spl) term.add_binaries(opts.file[0][0]) if opts.edcl and c.edcl != None: term.xfer.selectTransport("edcl") print("Preferred data transport: %s" % term.xfer.how) reset.resetToHost() term.loop()