Exemple #1
0
	def __enter__(self):
		logging.status("%s started" % self.name)

		# create pidfile
		open(self.pidfile, 'w').write(str(os.getpid()))

		return self
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
	def __exit__(self, type, value, traceback):
		logging.status("%s stopped" % self.name)

		# remove pidfile
		os.remove(self.pidfile)

		return False
Exemple #5
0
	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='')
Exemple #6
0
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()
Exemple #7
0
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('')
Exemple #8
0
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)
Exemple #9
0
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)
Exemple #10
0
	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.')
Exemple #11
0
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
Exemple #12
0
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)
Exemple #13
0
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')
Exemple #14
0
    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)
Exemple #15
0
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)
Exemple #16
0
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)
Exemple #17
0
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)
Exemple #18
0
    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="")
Exemple #19
0
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('')
Exemple #20
0
    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='')
Exemple #21
0
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)
Exemple #22
0
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)
Exemple #23
0
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)
Exemple #24
0
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)
Exemple #25
0
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)
Exemple #26
0
def command_set_attribute(args):
    tock_loader = TockLoader(args)
    tock_loader.open()

    logging.status('Setting attribute...')
    tock_loader.set_attribute(args.key, args.value)
Exemple #27
0
	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.')
Exemple #28
0
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)
Exemple #29
0
	# 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')
Exemple #30
0
def command_remove_attribute(args):
    tock_loader = TockLoader(args)
    tock_loader.open()

    logging.status('Removing attribute...')
    tock_loader.remove_attribute(args.key)
Exemple #31
0
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)