init: pin daemon stdio to boot-log VT1 so the login prompt lands last
Daemon stdio (fd 0/1/2) is inherited from bootstrap pointing at /scheme/debug — the kernel console — which fbcond renders onto the *active* VT. Once 29_activate_console switches the active VT to 2 for the getty login, any daemon that logs afterwards paints on top of the login banner/prompt: late async driver attach (i2c-hidd, evdevd, dw-acpi-i2cd, all via common::setup_logging -> stderr) and smolnetd's bounded NIC wait. So the banner ended up "near the end" but never last. Re-enable switch_stdio, redirecting daemon stdio to a fixed boot-log VT (/scheme/fbcon/1) right after the /usr switchroot, before the /usr units run. VT1 is the active console during boot (so the full boot stays visible there), fbcond still mirrors it to serial, and VT2 is left clean for a prompt that lands last. This is NOT the old /scheme/log redirect that went dark: that relied on fbbootlogd surfacing /scheme/log to the framebuffer (racy). A real VT renders directly. Best-effort: if fbcon/1 can't be opened, stdio stays on the kernel console exactly as before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-10
@@ -130,16 +130,6 @@ fn main() {
|
||||
scheduler
|
||||
.schedule_start_and_report_errors(&mut unit_store, UnitId("00_logd.service".to_owned()));
|
||||
scheduler.step(&mut unit_store, &mut init_config);
|
||||
// NOTE: init/daemon stdio is deliberately kept on the kernel console
|
||||
// rather than being redirected into /scheme/log. Redirecting made the boot
|
||||
// "go dark" after logd on text/recovery ISOs (bare/mini): the graphical
|
||||
// bootlog (fbbootlogd, VT1) does not reliably surface /scheme/log to the
|
||||
// framebuffer, and logd's console mirror is racy, so the console showed
|
||||
// nothing between logd and the login VT — indistinguishable from a hang.
|
||||
// Keeping stdio on the console makes the full boot observable on
|
||||
// `-serial` and the framebuffer. (A quiet/splash mode for the graphical
|
||||
// full ISO can re-enable the redirect once fbbootlogd rendering is fixed.)
|
||||
let _ = switch_stdio;
|
||||
|
||||
let runtime_target = UnitId("00_runtime.target".to_owned());
|
||||
scheduler.schedule_start_and_report_errors(&mut unit_store, runtime_target.clone());
|
||||
@@ -155,6 +145,29 @@ fn main() {
|
||||
Path::new("/usr"),
|
||||
Path::new("/etc"),
|
||||
);
|
||||
|
||||
// Pin init/daemon stdio to the dedicated boot-log VT (fbcon/1) before the
|
||||
// /usr units run. Rationale: stdio otherwise stays on the kernel console
|
||||
// (/scheme/debug), which fbcond renders onto the *active* VT. Once the
|
||||
// `29_activate_console` unit switches the active VT to 2 for the getty
|
||||
// login, any daemon that logs afterwards — late async driver attach
|
||||
// (i2c-hidd, evdevd, dw-acpi-i2cd) or smolnetd's bounded NIC wait — paints
|
||||
// its output on top of the login banner/prompt, so the prompt is never the
|
||||
// last thing on screen. Pinning daemon output to VT1 (a fixed VT, not the
|
||||
// active one) keeps the boot log fully visible — VT1 is the active console
|
||||
// during boot, and fbcond still mirrors it to the serial line — while
|
||||
// leaving VT2 clean for a login prompt that lands last.
|
||||
//
|
||||
// This is deliberately NOT the old `/scheme/log` redirect that made boot
|
||||
// "go dark": that depended on fbbootlogd surfacing /scheme/log to the
|
||||
// framebuffer (racy/unreliable). A real VT renders directly, so full-boot
|
||||
// observability is preserved. Best-effort: if fbcon/1 cannot be opened
|
||||
// (e.g. fbcond absent on a headless/serial-only boot), stdio stays on the
|
||||
// kernel console and the boot remains observable exactly as before.
|
||||
if let Err(err) = switch_stdio("/scheme/fbcon/1") {
|
||||
eprintln!("INIT: keeping stdio on kernel console (fbcon/1 unavailable: {err})");
|
||||
}
|
||||
|
||||
{
|
||||
// FIXME introduce multi-user.target unit and replace the config dir iteration
|
||||
// scheduler.schedule_start_and_report_errors(&mut unit_store, UnitId("multi-user.target".to_owned()));
|
||||
|
||||
Reference in New Issue
Block a user