From 5d7541677ff2edd072029375900351a112c0cb12 Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Tue, 13 Feb 2024 13:11:18 -0500 Subject: [PATCH] add --preserve-order flag This loads apps in the order they are given on the command line, and inserts padding if needed. --- tockloader/main.py | 9 +++++++ tockloader/tockloader.py | 58 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/tockloader/main.py b/tockloader/main.py index 3892bd3..cceb100 100644 --- a/tockloader/main.py +++ b/tockloader/main.py @@ -163,6 +163,10 @@ def command_install(args): replace = "yes" if args.no_replace: replace = "no" + if args.preserve_order: + # We are just going to append all specified apps in the order they are + # included on the command line. + 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) @@ -947,6 +951,11 @@ def main(): help="Modify the root TBF header when installing an app.", nargs=2, ) + install.add_argument( + "--preserve-order", + help="Install all specified TABs in the order they are on command line.", + action="store_true", + ) update = subparser.add_parser( "update", diff --git a/tockloader/tockloader.py b/tockloader/tockloader.py index 4fc7b55..8e47dd9 100644 --- a/tockloader/tockloader.py +++ b/tockloader/tockloader.py @@ -330,6 +330,9 @@ def install(self, tabs, replace="yes", erase=False, sticky=False): if len(tabs) == 0: raise TockLoaderException("No TABs to install") + # Check for the `--preserve-order` flag that `--erase` was also specified. + # We don't know + # Enter bootloader mode to get things started with self._start_communication_with_board(): # This is the architecture we need for the board. @@ -401,7 +404,9 @@ def install(self, tabs, replace="yes", erase=False, sticky=False): if changed: # Since something is now different, update all of the apps - self._reshuffle_apps(resulting_apps) + self._reshuffle_apps( + resulting_apps, preserve_order=self.args.preserve_order + ) else: # Nothing changed, so we can raise an error raise TockLoaderException("Nothing found to update") @@ -1198,7 +1203,7 @@ def _tickv_write_database(self, tickv_db): ## Helper Functions for Manipulating Binaries and TBF ############################################################################ - def _reshuffle_apps(self, apps): + def _reshuffle_apps(self, apps, preserve_order=False): """ Given an array of apps, some of which are new and some of which exist, sort them so we can write them to flash. @@ -1206,6 +1211,10 @@ def _reshuffle_apps(self, apps): This function is really the driver of tockloader, and is responsible for setting up applications in a way that can be successfully used by the board. + + If `preserve_order` is set to `True` this won't actually do any + shuffling, and will instead load apps with padding in the order they are + in the array. """ # @@ -1264,6 +1273,11 @@ def _reshuffle_apps(self, apps): # This is the fixed addresses case # + if preserve_order: + raise TockLoaderException( + "Cannot preserve order with fixed-address apps." + ) + def brad_sort(slices): """ Get an ordering of apps where the fixed start addresses are @@ -1427,7 +1441,11 @@ def is_valid(slices): # We are given an array of apps. First we need to order them based on # the ordering requested by this board (or potentially the user). - if self.app_settings["order"] == "size_descending": + if preserve_order: + # We already have our sort order if we are preserving the order. + # We use the order the apps were given to us. + pass + elif self.app_settings["order"] == "size_descending": apps.sort(key=lambda app: app.get_size(), reverse=True) elif self.app_settings["order"] == None: # Any order is fine. @@ -1482,6 +1500,21 @@ def is_valid(slices): # and special case this bundle operation. app_bundle = bytearray() for app in apps: + # Check if we might need to insert a padding app. + if self.app_settings["alignment_constraint"]: + if self.app_settings["alignment_constraint"] == "size": + # We need to make sure the app is aligned to a multiple + # of its size. + size = app.get_size() + multiple = app_address // size + if multiple * size != app_address: + # Not aligned. Insert padding app. + new_address = ((app_address + size) // size) * size + gap_size = new_address - app_address + padding = PaddingApp(gap_size) + app_bundle += padding + app_address = new_address + app_bundle += app.get_binary(app_address) app_address += app.get_size() logging.info( @@ -1493,6 +1526,25 @@ def is_valid(slices): # not be modified is if it was read off the board and nothing # changed. for app in apps: + # Check if we might need to insert a padding app. + if self.app_settings["alignment_constraint"]: + if self.app_settings["alignment_constraint"] == "size": + # We need to make sure the app is aligned to a multiple + # of its size. + size = app.get_size() + multiple = app_address // size + if multiple * size != app_address: + # Not aligned. Insert padding app. + new_address = ((app_address + size) // size) * size + gap_size = new_address - app_address + padding = PaddingApp(gap_size) + + logging.info("Flashing padding to board.") + self.channel.flash_binary( + app_address, padding.get_binary(app_address) + ) + app_address = new_address + # If we get a binary, then we need to flash it. Otherwise, # the app is already installed. optional_binary = app.get_binary(app_address)