def __enter__(self): logging.status("%s started" % self.name) # create pidfile open(self.pidfile, 'w').write(str(os.getpid())) return self
def command_tbf_modify_tlv(args): tabs = collect_tabs(args) if len(tabs) == 0: raise TockLoaderException("No TABs found, no TBF headers to process") tlvid = args.tlvid field = args.field value = args.value logging.status("Modifying TLV ID {} to set {}={}...".format( tlvid, field, value)) for tab in tabs: # Ask the user which TBF binaries to update. tbf_names = tab.get_tbf_names() index = helpers.menu( tbf_names + ["All"], return_type="index", title="Which TBF to modify TLV?", default_index=len(tbf_names), ) for i, tbf_name in enumerate(tbf_names): if i == index or index == len(tbf_names): app = tab.extract_tbf(tbf_name) app.modify_tbfh_tlv(tlvid, field, value) tab.update_tbf(app)
def command_flash(args): check_and_run_make(args) # Load in all binaries binary = bytes() count = 0 for binary_name in args.binary: # check that file isn't a `.hex` file if binary_name.endswith('.hex'): exception_string = 'Error: Cannot flash ".hex" files.' exception_string += ' Likely you meant to use a ".bin" file but used an intel hex file by accident.' raise TockLoaderException(exception_string) # add contents to binary with open(binary_name, 'rb') as f: binary += f.read() count += 1 # Check if the user asked us to pad the binary with some additional bytes. pad = None if args.pad: # First arg is the length, second arg is the value pad = (args.pad[0], args.pad[1]) if pad[1] < 0 or pad[1] > 255: raise TockLoaderException('Padding value must be only one byte') # Flash the binary to the chip tock_loader = TockLoader(args) tock_loader.open() plural = 'y' if count > 1: plural = 'ies' logging.status('Flashing binar{} to board...'.format(plural)) tock_loader.flash_binary(binary, args.address, pad=pad)
def __exit__(self, type, value, traceback): logging.status("%s stopped" % self.name) # remove pidfile os.remove(self.pidfile) return False
def run_terminal (self): ''' Use JLinkRTTClient to listen for RTT messages. ''' if self.jlink_device == None: logging.error('Unknown jlink_device. Use the --board or --jlink-device options.') return logging.status('Starting JLinkExe JTAG connection.') jtag_p = subprocess.Popen('{} -device {} -if {} -speed {} -autoconnect 1 -jtagconf -1,-1'.format( self.jlink_cmd, self.jlink_device, self.jlink_if, self.jlink_speed).split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Delay to give the JLinkExe JTAG connection time to start before running # the RTT listener. time.sleep(1) # Determine the name of the RTT binary to run. self.jlink_rtt_cmd = getattr(self.args, 'jlink_rtt_cmd') if self.jlink_rtt_cmd == None: self.jlink_rtt_cmd = 'JLinkRTTClient' logging.status('Starting {} to listen for messages.'.format(self.jlink_rtt_cmd)) p = subprocess.Popen('{}'.format(self.jlink_rtt_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE) for stdout_line in iter(p.stdout.readline, ""): l = stdout_line.decode("utf-8") if not l.startswith('###RTT Client: *'): print(l, end='')
def command_info(args): tock_loader = TockLoader(args) tock_loader.open() print('tockloader version: {}'.format(__version__)) logging.status('Showing all properties of the board...') tock_loader.info()
def command_inspect_tab(args): tabs = collect_tabs(args) if len(tabs) == 0: raise TockLoaderException('No TABs found to inspect') logging.status('Inspecting TABs...') for tab in tabs: # Print the basic information that is true about the TAB and all # contained TBF binaries. print(tab) # Ask the user if they want to see more detail about a certain TBF. tbf_names = tab.get_tbf_names() index = helpers.menu(tbf_names + ['None'], return_type='index', title='Which TBF to inspect further?') if index < len(tbf_names): print('') print('{}:'.format(tbf_names[index])) app = tab.extract_tbf(tbf_names[index]) print(textwrap.indent(str(app.get_header()), ' ')) # If the user asked for the crt0 header, display that for the # architecture if args.crt0_header: print(' crt0 header') print(textwrap.indent(app.get_crt0_header_str(), ' ')) print('')
def command_read (args): # Read the correct flash from the chip tock_loader = TockLoader(args) tock_loader.open(args) logging.status('Reading flash from the board...') tock_loader.read_flash(args.address, args.length)
def command_flash (args): check_and_run_make(args) # Load in all binaries binary = bytes() count = 0 for binary_name in args.binary: # check that file isn't a `.hex` file if binary_name.endswith('.hex'): exception_string = 'Error: Cannot flash ".hex" files.' exception_string += ' Likely you meant to use a ".bin" file but used an intel hex file by accident.' raise TockLoaderException(exception_string) # add contents to binary with open(binary_name, 'rb') as f: binary += f.read() count += 1 # Flash the binary to the chip tock_loader = TockLoader(args) tock_loader.open() plural = 'y' if count > 1: plural = 'ies' logging.status('Flashing binar{} to board...'.format(plural)) tock_loader.flash_binary(binary, args.address)
def remove_attribute (self, key): ''' Remove an existing attribute already stored on the board. ''' # Do some checking if len(key.encode('utf-8')) > 8: raise TockLoaderException('Key is too long. Must be 8 bytes or fewer.') # Enter bootloader mode to get things started with self._start_communication_with_board(): if not self._bootloader_is_present(): raise TockLoaderException('No bootloader found! That means there is nowhere for attributes to go.') # Create a null buffer to overwrite with out = bytes([0]*9) # Find if this attribute key already exists for index, attribute in enumerate(self.channel.get_all_attributes()): if attribute and attribute['key'] == key: logging.status('Found existing key at slot {}. Removing.'.format(index)) self.channel.set_attribute(index, out) break else: raise TockLoaderException('Error: Attribute does not exist.')
def collect_tabs (args): ''' Load in Tock Application Bundle (TAB) files. If none are specified, this searches for them in subfolders. Also allow downloading apps by name from a server. ''' tab_names = args.tab # Check if any tab files were specified. If not, find them based # on where this tool is being run. if len(tab_names) == 0 or tab_names[0] == '': logging.info('No TABs passed to tockloader.') logging.status('Searching for TABs in subdirectories.') # First check to see if things could be built that haven't been if os.path.isfile('./Makefile'): p = subprocess.Popen(['make', '-n'], stdout=subprocess.PIPE) out, err = p.communicate() # Check for the name of the compiler to see if there is work # to be done if 'arm-none-eabi-gcc' in out.decode('utf-8'): logging.warning('Warning! There are uncompiled changes!') logging.warning('You may want to run `make` before loading the application.') # Search for ".tab" files tab_names = glob.glob('./**/*.tab', recursive=True) if len(tab_names) == 0: raise TockLoaderException('No TAB files found.') logging.info('Using: {}'.format(tab_names)) # Concatenate the binaries. tabs = [] for tab_name in tab_names: # Check if this is a TAB locally, or if we should check for it # on a remote hosting server. if not urllib.parse.urlparse(tab_name).scheme and not os.path.exists(tab_name): logging.info('Could not find TAB named "{}" locally.'.format(tab_name)) response = helpers.menu(['No', 'Yes'], return_type='index', prompt='Would you like to check the online TAB repository for that app? ') if response == 0: # User said no, skip this tab_name. continue else: # User said yes, create that URL and try to load the TAB. tab_name = 'https://www.tockos.org/assets/tabs/{}.tab'.format(tab_name) try: tabs.append(TAB(tab_name, args)) except Exception as e: if args.debug: logging.debug('Exception: {}'.format(e)) logging.error('Error opening and reading "{}"'.format(tab_name)) return tabs
def command_uninstall (args): tock_loader = TockLoader(args) tock_loader.open() if len(args.name) != 0: logging.status('Removing app(s) {} from board...'.format(', '.join(args.name))) else: logging.status('Preparing to uninstall apps...') tock_loader.uninstall_app(args.name)
def command_update (args): check_and_run_make(args) tabs = collect_tabs(args) tock_loader = TockLoader(args) tock_loader.open() logging.status('Updating application{} on the board...'.format(helpers.plural(len(tabs)))) tock_loader.install(tabs, replace='only')
def set_attribute(self, key, value): ''' Download all attributes stored on the board. ''' # Do some checking if len(key.encode('utf-8')) > 8: raise TockLoaderException( 'Key is too long. Must be 8 bytes or fewer.') if len(value.encode('utf-8')) > 55: raise TockLoaderException( 'Value is too long. Must be 55 bytes or fewer.') # Enter bootloader mode to get things started with self._start_communication_with_board(): if not self._bootloader_is_present(): raise TockLoaderException( 'No bootloader found! That means there is nowhere for attributes to go.' ) # Create the buffer to write as the attribute out = bytes([]) # Add key out += key.encode('utf-8') out += bytes([0] * (8 - len(out))) # Add length out += bytes([len(value.encode('utf-8'))]) # Add value out += value.encode('utf-8') # Find if this attribute key already exists open_index = -1 for index, attribute in enumerate( self.channel.get_all_attributes()): if attribute: if attribute['key'] == key: logging.status( 'Found existing key at slot {}. Overwriting.'. format(index)) self.channel.set_attribute(index, out) break else: # Save where we should put this attribute if it does not # already exist. if open_index == -1: open_index = index else: if open_index == -1: raise TockLoaderException( 'Error: No open space to save this attribute.') else: logging.status( 'Key not found. Writing new attribute to slot {}'. format(open_index)) self.channel.set_attribute(open_index, out)
def check_and_run_make(args): ''' Checks for a Makefile, and it it exists runs `make`. ''' if hasattr(args, 'make') and args.make: if os.path.isfile('./Makefile'): logging.status('Running `make`...') p = subprocess.Popen(['make']) out, err = p.communicate() if p.returncode != 0: logging.error('Error running make.') sys.exit(1)
def check_and_run_make(args): """ Checks for a Makefile, and it it exists runs `make`. """ if hasattr(args, "make") and args.make: if os.path.isfile("./Makefile"): logging.status("Running `make`...") p = subprocess.Popen(["make"]) out, err = p.communicate() if p.returncode != 0: logging.error("Error running make.") sys.exit(1)
def command_install (args): check_and_run_make(args) # Load in all TABs tabs = collect_tabs(args) # Install the apps on the board tock_loader = TockLoader(args) tock_loader.open() # Figure out how we want to do updates replace = 'yes' if args.no_replace: replace = 'no' logging.status('Installing app{} on the board...'.format(helpers.plural(len(tabs)))) tock_loader.install(tabs, replace=replace, erase=args.erase, sticky=args.sticky)
def run_terminal(self): """ Use JLinkRTTClient to listen for RTT messages. """ if getattr(self, "jlink_device", None) == None: # Try to figure it out. self.open_link_to_board() # See if we succeeded. if getattr(self, "jlink_device", None) == None: logging.error( "Unknown jlink_device. Use the --board or --jlink-device options." ) return logging.status("Starting JLinkExe JTAG connection.") jtag_p = subprocess.Popen( "{} -device {} -if {} -speed {} -autoconnect 1 -jtagconf -1,-1". format(self.jlink_cmd, self.jlink_device, self.jlink_if, self.jlink_speed).split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) # Delay to give the JLinkExe JTAG connection time to start before running # the RTT listener. time.sleep(1) # Determine the name of the RTT binary to run. self.jlink_rtt_cmd = getattr(self.args, "jlink_rtt_cmd") if self.jlink_rtt_cmd == None: self.jlink_rtt_cmd = "JLinkRTTClient" logging.status("Starting {} to listen for messages.".format( self.jlink_rtt_cmd)) p = subprocess.Popen( "{}".format(self.jlink_rtt_cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) for stdout_line in iter(p.stdout.readline, ""): l = stdout_line.decode("utf-8") if not l.startswith("###RTT Client: *"): print(l, end="")
def command_inspect_tab (args): tabs = collect_tabs(args) if len(tabs) == 0: raise TockLoaderException('No TABs found to inspect') logging.status('Inspecting TABs...') for tab in tabs: print(tab) # If the user asked for the crt0 header, display that for each # architecture. if args.crt0_header: print(' crt0 header') archs = tab.get_supported_architectures() for arch in archs: print(' {}'.format(arch)) print(textwrap.indent(tab.get_crt0_header_str(arch), ' ')) print('')
def run_terminal(self): ''' Use JLinkRTTClient to listen for RTT messages. ''' # Do a mini `determine_current_board` here so we know what to pass to # JLinkExe. We don't bother trying to find this all automatically, for # now it will just have to be passed in. if self.jlink_device == None and self.board and self.board in self.KNOWN_BOARDS: board = self.KNOWN_BOARDS[self.board] self.jlink_device = board['jlink_device'] if 'jlink_speed' in board: self.jlink_speed = board['jlink_speed'] if 'jlink_if' in board: self.jlink_if = board['jlink_if'] if self.jlink_device == None: logging.error( 'Unknown jlink_device. Use the --board or --jlink-device options.' ) return logging.status('Starting JLinkExe JTAG connection.') jtag_p = subprocess.Popen( 'JLinkExe -device {} -if {} -speed {} -autoconnect 1 -jtagconf -1,-1' .format(self.jlink_device, self.jlink_if, self.jlink_speed).split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Delay to give the JLinkExe JTAG connection time to start before running # the RTT listener. time.sleep(1) logging.status('Starting JLinkRTTClient to listen for messages.') p = subprocess.Popen('JLinkRTTClient', stdout=subprocess.PIPE, stderr=subprocess.PIPE) for stdout_line in iter(p.stdout.readline, ""): l = stdout_line.decode("utf-8") if not l.startswith('###RTT Client: *'): print(l, end='')
def command_tbf_delete_tlv(args): tabs = collect_tabs(args) if len(tabs) == 0: raise TockLoaderException("No TABs found, no TBF headers to process") tlvid = args.tlvid logging.status("Removing TLV ID {} from TBF headers...".format(tlvid)) for tab in tabs: # Ask the user which TBF binaries to update. tbf_names = tab.get_tbf_names() index = helpers.menu( tbf_names + ["All"], return_type="index", title="Which TBF to delete TLV from?", default_index=len(tbf_names), ) for i, tbf_name in enumerate(tbf_names): if i == index or index == len(tbf_names): app = tab.extract_tbf(tbf_name) app.delete_tbfh_tlv(tlvid) tab.update_tbf(app)
def command_write (args): ''' Write flash range on the chip with a specific value. ''' tock_loader = TockLoader(args) tock_loader.open() # Only write a single byte. if args.value < 0 or args.value > 0xff: raise TockLoaderException('Can only write multiple copies of a single byte') logging.status('Writing flash on the board...') logging.status(' Address: {:#x}'.format(args.address)) logging.status(' Length: {} bytes'.format(args.length)) logging.status(' Value: {:#x}'.format(args.value)) tock_loader.write_flash(args.address, args.length, args.value)
def command_write(args): """ Write flash range on the chip with a specific value. """ tock_loader = TockLoader(args) tock_loader.open() # Only write a single byte. if args.value < 0 or args.value > 0xFF: raise TockLoaderException( "Can only write multiple copies of a single byte") logging.status("Writing flash on the board...") logging.status(" Address: {:#x}".format(args.address)) logging.status(" Length: {} bytes".format(args.length)) logging.status(" Value: {:#x}".format(args.value)) tock_loader.write_flash(args.address, args.length, args.value)
def command_read(args): ''' Read the correct flash range from the chip. ''' tock_loader = TockLoader(args) tock_loader.open() logging.status('Reading flash from the board...') logging.status(' Address: {:#x}'.format(args.address)) logging.status(' Length: {} bytes'.format(args.length)) tock_loader.read_flash(args.address, args.length)
def command_read(args): """ Read the correct flash range from the chip. """ tock_loader = TockLoader(args) tock_loader.open() logging.status("Reading flash from the board...") logging.status(" Address: {:#x}".format(args.address)) logging.status(" Length: {} bytes".format(args.length)) tock_loader.read_flash(args.address, args.length)
def command_set_attribute(args): tock_loader = TockLoader(args) tock_loader.open() logging.status('Setting attribute...') tock_loader.set_attribute(args.key, args.value)
def uninstall_app (self, app_names): ''' If an app by this name exists, remove it from the chip. If no name is given, present the user with a list of apps to remove. ''' # Enter bootloader mode to get things started with self._start_communication_with_board(): # Get a list of installed apps apps = self._extract_all_app_headers() # If the user didn't specify an app list... if len(app_names) == 0: if len(apps) == 0: raise TockLoaderException('No apps are installed on the board') elif len(apps) == 1: # If there's only one app, delete it app_names = [apps[0].get_name()] logging.info('Only one app on board.') else: options = ['** Delete all'] options.extend([app.get_name() for app in apps]) name = helpers.menu(options, return_type='value', prompt='Select app to uninstall ', title='There are multiple apps currently on the board:') if name == '** Delete all': app_names = [app.get_name() for app in apps] else: app_names = [name] logging.status('Attempting to uninstall:') for app_name in app_names: logging.status(' - {}'.format(app_name)) # Remove the apps if they are there removed = False keep_apps = [] for app in apps: # Only keep apps that are not marked for uninstall or that # are sticky (unless force was set) if app.get_name() not in app_names or (app.is_sticky() and not self.args.force): keep_apps.append(app) else: removed = True # Tell the user if we are not removing certain apps because they are # sticky, or if we are removing apps because --force was provided. if not self.args.force: for app in apps: if app.get_name() in app_names and app.is_sticky(): logging.info('Not removing app "{}" because it is sticky.'.format(app)) logging.info('To remove this you need to include the --force option.') else: for app in apps: if app.get_name() in app_names and app.is_sticky(): logging.info('Removing sticky app "{}" because --force was used.'.format(app)) # Check if we actually have any work to do. if removed: # Now take the remaining apps and make sure they are on the # board properly. self._reshuffle_apps(keep_apps) logging.status('Uninstall complete.') if self.args.debug: # And let the user know the state of the world now that we're done apps = self._extract_all_app_headers() if len(apps): logging.info('After uninstall, remaining apps on board: ', end='') self._print_apps(apps, verbose=False, quiet=True) else: loggging.info('After uninstall, no apps on board.') else: raise TockLoaderException('Could not find any apps on the board to remove.')
def command_dump_flash_page(args): tock_loader = TockLoader(args) tock_loader.open() logging.status('Getting page of flash...') tock_loader.dump_flash_page(args.page)
# formatter formatter = MyFormatter( fmt = '%(asctime)s %(levelname)-8s %(fname)-20s %(message)s', datefmt = '%b %d %Y %H:%M:%S', ) handler.setFormatter(formatter) # custom levels logging.addLevelName(75, 'EXCEPT') logging.exception = log_exception logging.addLevelName(100, 'STATUS') logging.status = log_status # test if __name__ == '__main__': config_logger() logging.warning('test') logging.info('test') logging.debug('test') logging.error('test') try: err_var except Exception as ex: logging.exception() logging.status('test')
def command_remove_attribute(args): tock_loader = TockLoader(args) tock_loader.open() logging.status('Removing attribute...') tock_loader.remove_attribute(args.key)
def command_set_start_address(args): tock_loader = TockLoader(args) tock_loader.open() logging.status('Setting bootloader jump address...') tock_loader.set_start_address(args.address)