netboot: hold the screen on failure, dump the descriptor, shrink the block
Two separate problems, one of which was hiding the other. 1. The diagnostics were unreadable. do_netboot() printed them and returned, and the caller's draw_main() redrew immediately and wiped the screen -- so two consecutive failures were reported only as "a short flash" with no detail, and the error code alone was not enough to act on. nb_pause() now holds the screen until a button is pressed, on every failure path. This cost two blind round trips, each of which needs a hand copy of the .dol to the SD card. Printing a diagnosis and then erasing it is worse than not printing one. 2. The default block was 1024 bytes, making ~1050-byte frames that span FIVE of the SPRAM ring's 15 pages. The only multi-page frame ever proven on this hardware is the 342-byte DHCP broadcast from bring-up, which spans two. Five-page frames are untested territory, and a transfer is the wrong place to discover a wrap bug. Default is now 256 bytes -> ~296-byte frame -> two pages, deliberately close to the proven case. --block raises it once small blocks work; the GC still caps at NB_BLOCK_MAX = 1024. ring_next() also keeps the four raw descriptor bytes and the page it read them from, and the error path prints them. When a length is rejected those bytes ARE the diagnosis: 00 00 xx xx tells us the assembler wrote a descriptor and the length is simply unexpected, whereas garbage tells us we are reading the wrong page. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -125,6 +125,21 @@ static void nb_status(const char *msg)
|
||||
printf(" %s\n", msg);
|
||||
}
|
||||
|
||||
/* Hold the screen until a button is pressed. Without this the caller's
|
||||
* draw_main() redraws immediately and wipes every diagnostic line netboot
|
||||
* just printed -- which is exactly why the first two failures were reported
|
||||
* as "a short flash" with no detail. */
|
||||
static void nb_pause(const char *why)
|
||||
{
|
||||
printf("\n" C_DIM " %s -- press any button to return to the menu\n" C_RESET,
|
||||
why);
|
||||
for (;;) {
|
||||
VIDEO_WaitVSync();
|
||||
PAD_ScanPads();
|
||||
if (PAD_ButtonsDown(0)) return;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_netboot(char *status, size_t nstatus)
|
||||
{
|
||||
int len, rc;
|
||||
@@ -147,11 +162,13 @@ static void do_netboot(char *status, size_t nstatus)
|
||||
len = netboot_receive(s_stage, s_stage_max, nb_status);
|
||||
if (len <= 0) {
|
||||
snprintf(status, nstatus, "net-update failed (%d)", len);
|
||||
nb_pause("transfer failed");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = netboot_sd_write(netboot_dest_path(), s_stage, (u32)len, nb_status);
|
||||
if (rc < 0) {
|
||||
nb_pause("SD write failed");
|
||||
/* Nothing has been launched and nothing is half-written that we
|
||||
* know of, so staying in the menu is the safe outcome. */
|
||||
snprintf(status, nstatus,
|
||||
@@ -166,6 +183,7 @@ static void do_netboot(char *status, size_t nstatus)
|
||||
/* Reuse the staging region: the new build is already on the card and
|
||||
* verified, so the copy in RAM is finished with. */
|
||||
rc = netboot_boot_file("/boot.dol", s_stage, s_stage_max, nb_status);
|
||||
nb_pause("boot refused");
|
||||
|
||||
/* Only reached on refusal. The new build IS on the card either way,
|
||||
* so this is recoverable by rebooting into Swiss by hand. */
|
||||
|
||||
Reference in New Issue
Block a user