netboot: locate the descriptor, report the offset split, stop scrolling

Hardware with RBFI active: "timeout mid-transfer (5 seen, 18 bad desc, 0
lapped)", plus a frame dump of "1E FF FF FF FF FF FF 00".

Three things that tells us:
  - lapped = 0, so the ring is no longer being overwritten.  RBFI works and
    overflow is eliminated as the cause.
  - got > 0 ("mid-transfer"), so some blocks DID arrive and match.
  - 0x1E is 286 & 0xFF, the low byte of total_len, followed by the full
    six-byte broadcast MAC and then 0x00.  The frame body is intact but starts
    one byte later than the reader expects.

18 of 23 frames rejected while 5 parsed in the SAME run means the offset
VARIES frame to frame -- a race in the assembler, not a constant.  Simulation
does not reproduce it: T2/T5 put the descriptor at +0 and the body at +4 with
the write port both free-running and stalled 1-in-3, and the mutation controls
for both known handshake bugs fail as expected.  So the cause is still unknown
and I am not going to guess at it a fifth time.

ring_next() now LOCATES the descriptor instead of assuming +0: it probes
offsets 0 and 1 and takes whichever yields a plausible length (> 4 descriptor
bytes, <= a legal frame), then reads the body and advances RRP from that same
offset.  A length is a strong discriminator, so this is a measurement rather
than a guess, and it both lets the transfer proceed and COUNTS the split --
"desc@+0=N +1=M" on success and on timeout.  That distribution is the
measurement needed to find the real gateware bug.

Also trimmed the on-screen guidance: the console holds ~25 lines and the
explanatory text was pushing the failure diagnostics off the top, which cost
two blind round trips.  Status during a transfer is now one line, and the
menu blurb one line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 18:45:00 +02:00
parent 2aa50a7cc3
commit 4831c1353c
2 changed files with 51 additions and 22 deletions
+6 -6
View File
@@ -146,12 +146,12 @@ static void do_netboot(char *status, size_t nstatus)
printf("\n" C_HEAD " Self-update over the BBA" C_RESET "\n\n");
printf(" On the host: sudo ./scripts/send-dol.py <iface> <file.dol>\n\n");
printf(C_DIM " The received build is written to a TEMP file, verified, and\n"
" only then rotated in -- the previous build is kept alongside it\n"
" as <name>.prev.dol, so if the new one is broken you can boot the\n"
" old one from Swiss and try the transfer again.\n"
" Nothing received is ever launched directly: this boots /boot.dol,\n"
" your known-good Swiss.\n" C_RESET "\n");
/* Deliberately terse: the console holds ~25 lines and the diagnostics
* printed during a failed transfer are what matter. Explanatory text
* here pushed them off the top of the screen, which cost two blind
* round trips. */
printf(C_DIM " temp+verify+rotate; keeps <name>.prev.dol; boots /boot.dol\n"
C_RESET);
printf(" Blocks until done or it times out (30 s idle, 5 s mid-xfer).\n\n");
if (!s_stage) {