Skip to content

Commit 8d16f80

Browse files
committed
improve showing address map
add tockloader list --map
1 parent dfa4a15 commit 8d16f80

File tree

3 files changed

+108
-28
lines changed

3 files changed

+108
-28
lines changed

tockloader/display.py

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ def get(self):
4848
return self.out
4949

5050

51+
def choose(b, t, f):
52+
if b:
53+
return t
54+
return f
55+
56+
57+
def start_of_app(width, address):
58+
return "{:>#10x}┬{}┐\n".format(address, "─" * width)
59+
60+
61+
def end_of_app(width, address, continuing):
62+
left_corner = choose(continuing, "┼", "┴")
63+
right_corner = choose(continuing, "┤", "┘")
64+
return "{:>#10x}{}{}{}\n".format(address, left_corner, "─" * width, right_corner)
65+
66+
67+
def app_bracket(width, left, right):
68+
if len(left) + len(right) >= (width - 1):
69+
room_for_left = width - 1 - 1 - len(right)
70+
left = "{}…".format(left[0:room_for_left])
71+
left_size = width - len(right)
72+
content = "{:<{left_size}}{}".format(left, right, left_size=left_size)
73+
return "{}│{}│\n".format(" " * 10, content)
74+
75+
5176
class HumanReadableDisplay(Display):
5277
"""
5378
Format output as a string meant to be human readable.
@@ -87,30 +112,21 @@ def list_apps(self, apps, verbose, quiet):
87112
# In quiet mode just show the names.
88113
self.out += " ".join([app.get_name() for app in apps])
89114

90-
def show_app_map(self, apps, start_address):
91-
def choose(b, t, f):
92-
if b:
93-
return t
94-
return f
95-
96-
def start_of_app(width, address):
97-
return "{:>#10x}┬{}┐\n".format(address, "─" * width)
98-
99-
def end_of_app(width, address, continuing):
100-
left_corner = choose(continuing, "┼", "┴")
101-
right_corner = choose(continuing, "┤", "┘")
102-
return "{:>#10x}{}{}{}\n".format(
103-
address, left_corner, "─" * width, right_corner
104-
)
105-
106-
def app_bracket(width, left, right):
107-
if len(left) + len(right) >= (width - 1):
108-
room_for_left = width - 1 - 1 - len(right)
109-
left = "{}…".format(left[0:room_for_left])
110-
left_size = width - len(right)
111-
content = "{:<{left_size}}{}".format(left, right, left_size=left_size)
112-
return "{}│{}│\n".format(" " * 10, content)
113-
115+
def show_app_map_from_address(self, apps, start_address):
116+
"""
117+
Print a layout map of apps assuming they are located back-to-back
118+
starting from `start_address`. Example:
119+
120+
```
121+
0x30000┬──────────────────────────────────────────────────┐
122+
│App: blink [Installed]│
123+
│ Length: 16384 (0x4000) │
124+
0x34000┼──────────────────────────────────────────────────┤
125+
│App: blink [Installed]│
126+
│ Length: 16384 (0x4000) │
127+
0x3c000┴──────────────────────────────────────────────────┘
128+
```
129+
"""
114130
out = ""
115131
address = start_address
116132
for i, app in enumerate(apps):
@@ -136,6 +152,54 @@ def app_bracket(width, left, right):
136152

137153
self.out += out
138154

155+
def show_app_map_actual_address(self, apps):
156+
"""
157+
Show a map of installed applications with known addresses. Example:
158+
159+
```
160+
0x30000┬──────────────────────────────────────────────────┐
161+
│App: blink [Installed]│
162+
│ Length: 16384 (0x4000) │
163+
0x34000┴──────────────────────────────────────────────────┘
164+
0x38000┬──────────────────────────────────────────────────┐
165+
│App: blink [Installed]│
166+
│ Length: 16384 (0x4000) │
167+
0x3c000┴──────────────────────────────────────────────────┘
168+
```
169+
"""
170+
171+
out = ""
172+
prev_address = -1
173+
for i, app in enumerate(apps):
174+
size = app.get_size()
175+
active_address = app.get_address()
176+
177+
if active_address != prev_address:
178+
out += start_of_app(50, active_address)
179+
180+
if isinstance(app, TabApp):
181+
title = "App: {}".format(app.get_name())
182+
out += app_bracket(50, title, "[From TAB]")
183+
elif isinstance(app, InstalledApp):
184+
title = "App: {}".format(app.get_name())
185+
out += app_bracket(50, title, "[Installed]")
186+
elif isinstance(app, PaddingApp):
187+
out += app_bracket(50, "Padding", "")
188+
out += app_bracket(50, " Length: {} ({:#x})".format(size, size), "")
189+
190+
prev_address = active_address + size
191+
192+
# Check if the next app starts at the address the current app ends
193+
# at.
194+
immediately_after = False
195+
if i < len(apps) - 1:
196+
next_address = apps[i + 1].get_address()
197+
immediately_after = prev_address == next_address
198+
199+
out += end_of_app(50, prev_address, immediately_after)
200+
201+
self.out += out
202+
139203
def show_board_visual(self, apps):
140204
def horizontal_add(existing, new):
141205
existing_lines = existing.split("\n")

tockloader/main.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,15 @@ def command_list(args):
144144
with open(key_path, "rb") as f:
145145
public_keys.append(f.read())
146146

147+
verbose = args.verbose
148+
if args.map:
149+
# We always want verbose if showing the map so we see all apps including
150+
# padding.
151+
verbose = True
152+
147153
tock_loader = TockLoader(args)
148154
tock_loader.open()
149-
tock_loader.list_apps(args.verbose, args.quiet, public_keys)
155+
tock_loader.list_apps(verbose, args.quiet, args.map, public_keys)
150156

151157

152158
def command_install(args):
@@ -1013,6 +1019,11 @@ def main():
10131019
help="Print just a list of application names",
10141020
action="store_true",
10151021
)
1022+
listcmd.add_argument(
1023+
"--map",
1024+
help="Print a table with apps and addresses",
1025+
action="store_true",
1026+
)
10161027
listcmd.add_argument(
10171028
"--verify-credentials",
10181029
help="Check credentials with a list of public keys",

tockloader/tockloader.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,13 @@ def flash_binary(self, binary, address, pad=None):
301301
logging.debug("Unable to set attribute after flash command.")
302302
logging.debug(ret)
303303

304-
def list_apps(self, verbose, quiet, verify_credentials_public_keys):
304+
def list_apps(self, verbose, quiet, map, verify_credentials_public_keys):
305305
"""
306306
Query the chip's flash to determine which apps are installed.
307307
308308
- `verbose` - bool: Show details about TBF.
309309
- `quiet` - bool: Just show the app name.
310+
- `map` - bool: Show a diagram listing apps with addresses.
310311
- `verify_credentials_public_keys`: Either `None`, meaning do not verify
311312
any credentials, or a list of public keys binaries to use to help
312313
verify credentials. The list can be empty and all credentials that can
@@ -333,7 +334,11 @@ def list_apps(self, verbose, quiet, verify_credentials_public_keys):
333334
else:
334335
displayer = display.HumanReadableDisplay()
335336

336-
displayer.list_apps(apps, verbose, quiet)
337+
if map:
338+
displayer.show_app_map_actual_address(apps)
339+
else:
340+
displayer.list_apps(apps, verbose, quiet)
341+
337342
print(displayer.get())
338343

339344
def install(self, tabs, replace="yes", erase=False, sticky=False, layout=None):
@@ -1457,7 +1462,7 @@ def is_valid(slices):
14571462

14581463
logging.info("App Layout:")
14591464
displayer = display.HumanReadableDisplay()
1460-
displayer.show_app_map(to_flash_apps, address)
1465+
displayer.show_app_map_from_address(to_flash_apps, address)
14611466
app_layout = displayer.get()
14621467
for l in app_layout.splitlines():
14631468
logging.info(l)

0 commit comments

Comments
 (0)