Skip to content

Commit

Permalink
add --preserve-order flag
Browse files Browse the repository at this point in the history
This loads apps in the order they are given on the command line, and
inserts padding if needed.
  • Loading branch information
bradjc committed Feb 13, 2024
1 parent a3d173a commit 5d75416
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 3 deletions.
9 changes: 9 additions & 0 deletions tockloader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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",
Expand Down
58 changes: 55 additions & 3 deletions tockloader/tockloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -1198,14 +1203,18 @@ 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.
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.
"""

#
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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(
Expand All @@ -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)
Expand Down

0 comments on commit 5d75416

Please sign in to comment.