Skip to content

Commit 156b272

Browse files
committed
imx95-pqc-demo: show wolfBoot's verified boot of Linux until the benchmarks start
1 parent abcbb9c commit 156b272

1 file changed

Lines changed: 39 additions & 6 deletions

File tree

‎imx95-pqc-demo/demo/twopane.py‎

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
CONTAINER = os.environ.get("CONTAINER", "wolfcrypt-pqc")
2828
MEMTOOL = os.environ.get("MEMTOOL", "/home/torizon/bin/memtool")
2929
CONSOLE_ADDR = os.environ.get("CONSOLE_ADDR", "0x80F00000")
30+
A55_CONSOLE_ADDR = os.environ.get("A55_CONSOLE_ADDR", "0x80F20000")
3031
INTERVAL = float(os.environ.get("INTERVAL", "1.0"))
3132

3233
ANSI = re.compile(r"\x1b\[[0-9;]*[A-Za-z]")
@@ -41,6 +42,15 @@
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+
4454
OPS = re.compile(r"^(.*?)\s+\d+ ops took [\d.]+ sec, avg [\d.]+ ms,\s+([\d.]+) ops/sec")
4555
THRU = 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

8696
LEFT_TITLE = " Cortex-A55: wolfCrypt PQC (on 1 of 6 cores) "
97+
LEFT_BOOT_TITLE = " Cortex-A55: wolfBoot ML-DSA-87 "
8798
RIGHT_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+
142158
def 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):
163179
def 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

Comments
 (0)