2727CONTAINER = os .environ .get ("CONTAINER" , "wolfcrypt-pqc" )
2828MEMTOOL = os .environ .get ("MEMTOOL" , "/home/torizon/bin/memtool" )
2929CONSOLE_ADDR = os .environ .get ("CONSOLE_ADDR" , "0x80F00000" )
30+ A55_CONSOLE_ADDR = os .environ .get ("A55_CONSOLE_ADDR" , "0x80F20000" )
3031INTERVAL = float (os .environ .get ("INTERVAL" , "1.0" ))
3132
3233ANSI = re .compile (r"\x1b\[[0-9;]*[A-Za-z]" )
4142# The raw benchmark line is far too wide for half a console, and truncating it
4243# cuts off ops/sec - the one number worth showing. Condense to
4344# "<algorithm> <operation> <rate>" so each result fits on one readable row.
45+ # The A55 boot log is long and most of it is bookkeeping: the handoff register
46+ # dump, the MBR walk, and a line per FIT sub-image copied. Only the chain of
47+ # trust belongs on a demo screen, and the pane holds far fewer rows than the log
48+ # has lines, so without this the verification scrolls off before anyone reads it.
49+ BOOT_KEEP = re .compile (
50+ r"^(wolfBoot:|scmi:|usdhc:|Boot partition:|Booting version|"
51+ r"Checking image integrity|Verifying image signature|info: ML-DSA|"
52+ r"info: using ML-DSA|info: wc_MlDsaKey_Verify|Firmware Valid|Booting at)" )
53+
4454OPS = re .compile (r"^(.*?)\s+\d+ ops took [\d.]+ sec, avg [\d.]+ ms,\s+([\d.]+) ops/sec" )
4555THRU = re .compile (r"^(\S.*?)\s+[\d.]+ [KMG]iB took [\d.]+ seconds,\s+([\d.]+) ([KMG]iB/s)" )
4656
@@ -84,6 +94,7 @@ def condense(ln, width):
8494 return f"{ shorten (m .group (1 ))[:wname ]:<{wname }} { value :>{len (value )}} "
8595
8696LEFT_TITLE = " Cortex-A55: wolfCrypt PQC (on 1 of 6 cores) "
97+ LEFT_BOOT_TITLE = " Cortex-A55: wolfBoot ML-DSA-87 "
8798RIGHT_TITLE = " Cortex-M7: wolfBoot ML-DSA-87 "
8899
89100
@@ -139,6 +150,11 @@ def text(self):
139150 return "\n " .join (self .buf )
140151
141152
153+ def boot_lines (text ):
154+ """Keep only the chain-of-trust lines from wolfBoot's own boot log."""
155+ return [ln for ln in text .splitlines () if BOOT_KEEP .match (ln .strip ())]
156+
157+
142158def clean (text , width , drop_cycles = False ):
143159 """Strip ANSI so column widths are computed on what is actually shown.
144160
@@ -163,10 +179,12 @@ def clean(text, width, drop_cycles=False):
163179def fit (lines , width , height , wrap = False ):
164180 """Last `height` lines, fitted to `width`.
165181
166- The benchmark pane truncates: its lines are already condensed to fit, and a
167- wrapped one would cost extra rows and break alignment. The wolfBoot pane
168- wraps: its output is short, it is the point of the demo, and losing the end
169- of "wc_MlDsaKey_Verify returned OK" would defeat the purpose.
182+ Both panes wrap. The wolfBoot panes must: their output is the point of the
183+ demo, and losing the end of "wc_MlDsaKey_Verify returned OK" would defeat
184+ it. The benchmark pane is already condensed to the pane width, so wrapping
185+ is normally a no-op there, and it is still what we want in the narrow case
186+ condense() cannot squeeze (a long value clamps the label at six columns and
187+ the line runs over) - an extra row beats a silently cut number.
170188 """
171189 out = []
172190 for ln in lines :
@@ -198,15 +216,30 @@ def main():
198216 half = (cols - 3 ) // 2
199217 body = rows - 4
200218
201- left = fit (clean (logtail .text (), half , drop_cycles = True ), half , body , wrap = True )
219+ # The left pane tells the A55's story in the order it happened: first
220+ # wolfBoot verifying the kernel it booted (read back from the DDR ring,
221+ # since that output is long gone from the console by the time anything
222+ # can render), then the benchmarks, from the moment the container has a
223+ # result worth showing.
224+ bench = clean (logtail .text (), half , drop_cycles = True )
225+ if bench :
226+ left_title = LEFT_TITLE
227+ left = fit (bench , half , body , wrap = True )
228+ else :
229+ left_title = LEFT_BOOT_TITLE
230+ boot_raw = run (f"{ MEMTOOL } con { A55_CONSOLE_ADDR } 2>/dev/null" )
231+ boot = boot_lines (ANSI .sub ("" , boot_raw ))
232+ if not boot :
233+ boot = ["waiting for the benchmark container ..." ]
234+ left = fit (boot , half , body , wrap = True )
202235 right_raw = run (f"{ MEMTOOL } con { CONSOLE_ADDR } 2>/dev/null" )
203236 if not right_raw .strip ():
204237 right_raw = "waiting for the Cortex-M7 to boot ...\n "
205238 right = fit (clean (right_raw , half ), half , body , wrap = True )
206239
207240 buf = ["\x1b [?25l\x1b [H" ] # hide cursor, home - no clear, see note above
208241 buf .append ("\x1b [1;36m" + "NXP i.MX95 - post-quantum on both clusters" .center (cols ) + "\x1b [0m" )
209- buf .append ("\x1b [1;33m" + LEFT_TITLE .ljust (half ) + " | " +
242+ buf .append ("\x1b [1;33m" + left_title .ljust (half ) + " | " +
210243 RIGHT_TITLE .ljust (half ) + "\x1b [0m" )
211244 buf .append ("-" * cols )
212245 for i in range (body ):
0 commit comments