gfx: the chosen resolution reaches every head, and the greeting stops racing

Two things.

**The F8 resolution now applies to the other displays as well.** It already
reached them once vgpud started -- that was the last commit but one -- but not
before: choosing 1024x768 changed the screen it was chosen on and left the
other at 1280x800, so the menu and then the splash appeared on it as a small
rectangle in the middle of a larger black one. Which is a fair reading of "the
resolution change is not changing resolution".

The resolution offered in that menu is a statement about the machine's display,
not about one adapter of it, so both stages before vgpud now follow it:

  the loader   mirrors_match() puts every mirror GOP into the primary's mode,
               called from mirrors_show() so it cannot be forgotten at a new
               call site. Two integer comparisons in the common case.
  the kernel   setup_scanout() takes gfx's dimensions over GET_DISPLAY_INFO's.
               Same argument as vgpud's bring_up(): the host window's size is
               a fact about QEMU, and the console's mode is the one somebody
               chose.

**And the greeting is no longer a race.** "Welcome to SchOS!" was printed after
every job had been started, including the shell on the console -- so which of
the two reached the screen first was up to the scheduler, and it went both ways
about evenly. A boot that sometimes greets you above the prompt and sometimes
below it does not read as two orderings of one boot; it reads as a line printed
by mistake.

schinitd now holds back the job that owns the console -- `own_tty`, which is
exactly the job whose output lands there -- until after the greeting is
written. That is enough to settle it: this process writes the line, and only
then asks PID 1 to spawn the shell, so the fork has not happened yet. Nothing
waits on it that was not already waiting.

Verified: F8 -> Resolution -> 1024x768 -> boot, with the virtio head
screendumped over QMP at three points during startup and once at the prompt --
1024x768 throughout, and byte-identical to the stdvga head. Three consecutive
boots put the greeting at the same offset, ahead of the prompt every time.
Both supported configurations: one boot each, no traps, no panics, socktest and
memfdtest green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nexoniarz 2026-09-22 22:19:00 +02:00
commit 9ab8a7a426
4 changed files with 95 additions and 1 deletions

View file

@ -1045,6 +1045,45 @@ mirrors_find(EFI_GRAPHICS_OUTPUT_PROTOCOL *primary)
}
}
/* Put every mirror into the primary's mode, if it has one.
*
* Without this, choosing 1024x768 at the F8 menu changed the screen it was
* chosen on and left the other one at whatever the firmware had picked -- so
* the menu and then the splash appeared on it as a small rectangle in the
* middle of a larger black one. The resolution in that menu is a statement
* about the machine's display, not about one adapter of it.
*
* Cheap to call on every frame: the common case is two integer comparisons and
* no mode set at all. A mirror with no matching mode keeps the one it has and
* gets the centred-and-cropped treatment below, which is still better than
* nothing.
*/
static void
mirrors_match(EFI_GRAPHICS_OUTPUT_PROTOCOL *primary)
{
UINT32 w = primary->Mode->Info->HorizontalResolution;
UINT32 h = primary->Mode->Info->VerticalResolution;
for (UINTN i = 0; i < mirror_n; i++) {
EFI_GRAPHICS_OUTPUT_PROTOCOL *g = mirror_gop[i];
if (g->Mode->Info->HorizontalResolution == w &&
g->Mode->Info->VerticalResolution == h)
continue;
for (UINT32 m = 0; m < g->Mode->MaxMode; m++) {
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi = 0;
UINTN sz = 0;
if (EFI_ERROR(g->QueryMode(g, m, &sz, &mi)) || !mi)
continue;
if (mi->HorizontalResolution == w && mi->VerticalResolution == h) {
g->SetMode(g, m);
break;
}
}
}
}
/* Put what is on the primary onto all of them. Centred when the sizes differ,
* cropped when the other display is smaller -- the same rules the kernel's
* console mirror and vgpud's both use, because it is the same picture. */
@ -1058,6 +1097,8 @@ mirrors_show(void)
if (!primary->Mode->FrameBufferBase)
return; /* nothing to copy *from* */
mirrors_match(primary);
UINTN sw = primary->Mode->Info->HorizontalResolution;
UINTN sh = primary->Mode->Info->VerticalResolution;
UINTN delta = (UINTN)primary->Mode->Info->PixelsPerScanLine * 4;