boot: one line when it works, all of it when it does not
A boot printed about thirty lines before reaching a prompt. Every one was
useful once, and printed on every boot for ever they train the person in front
of the machine to stop reading their own console -- which is expensive on the
day one of them changes.
SchOS UEFI loader
Press F8 for boot options... booting
Welcome to SchOS! (F8 at boot for the full log, or dmesg once you are in)
root@schos / »
**Nothing was deleted, it was routed.** consputc() already wrote to the klog
ring before anywhere else, so a line can be kept in full while being held back
from the two places a person looks. kinfo() is cprintf() with that routing, and
`dmesg` still has the whole boot with timestamps afterwards. The rule for which
is which is not how interesting a line is -- everything was interesting to
somebody once -- but whether you would want to see it on a machine that is
*working*. `pci: 7 devices` is yes the first time and no every time after;
`e1000: no DMA memory for the rings` is yes for ever and stays a cprintf.
The verbose boot the F8 menu already offered now means something much bigger,
which is the other half of this: it is the only way to see any of it live.
Userspace follows through /proc/bootmode, one word. schinit, schinitd and vgpud
hold back their progress lines and never their failures -- a supervisor that
goes quiet when a job dies is worse than one that chatters.
Two things found by testing rather than by reading:
- schinit read /proc/bootmode *before* bootstrap() mounted /proc, so it got
"quiet" every time and the verbose boot was quiet in the one process that
runs first. It reads after the mount now.
- resolvconf announced "already exists; -f to replace it" on every boot after
the first, which is a line about having done nothing. It is quiet when the
file already says what it would have written, and speaks only when the two
disagree -- which means the nameserver changed and the machine is using the
old one.
Verified both ways: quiet boot is six lines, a forced-verbose build prints all
thirty plus the `verbose boot:` steps, and /proc/kmsg holds every line in both.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
This commit is contained in:
parent
c028561da0
commit
617a4aec0a
24 changed files with 373 additions and 60 deletions
|
|
@ -207,9 +207,71 @@ framebuffer from the loader. Then everything goes to the UART and
|
|||
|
||||
---
|
||||
|
||||
## 7. What the boot says
|
||||
|
||||
A working boot prints one line:
|
||||
|
||||
```
|
||||
SchOS UEFI loader
|
||||
Press F8 for boot options... booting
|
||||
|
||||
Welcome to SchOS! (F8 at boot for the full log, or dmesg once you are in)
|
||||
|
||||
root@schos / »
|
||||
```
|
||||
|
||||
It used to print about thirty — the memory map, the local APIC's calibration,
|
||||
every PCI device, each driver announcing itself, each job starting. All of that
|
||||
is genuinely useful, and all of it is useful *once*. Printed on every boot it
|
||||
trains the person in front of the machine to stop reading their own console,
|
||||
which is expensive on the day one of those lines changes.
|
||||
|
||||
**Nothing was deleted; it was routed.** `consputc()` writes to the klog ring
|
||||
before it writes anywhere else, so a line can be kept in full while being held
|
||||
back from the two places a person is looking. `kinfo()` is `cprintf()` with
|
||||
that routing, and the whole boot is still there afterwards:
|
||||
|
||||
```
|
||||
# dmesg | head -4
|
||||
--- boot 1 ---
|
||||
[ 0.00] e820: 1017 MB usable in 8 regions, top 1006 MB (22 entries)
|
||||
[ 0.00] acpi: 2 cpus, lapic at ffff8000fee00000, ioapic id 0
|
||||
[ 0.00] pci: 7 devices
|
||||
```
|
||||
|
||||
The rule for `kinfo` against `cprintf` is not how interesting a line is —
|
||||
everything was interesting to somebody once. It is: **would you want to see
|
||||
this on a machine that is working?** `pci: 7 devices` is yes the first time and
|
||||
no every time after. `e1000: no DMA memory for the rings` is yes for ever, and
|
||||
stays a `cprintf`.
|
||||
|
||||
Three levels, then, and the middle one is new:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| quiet (default) | the greeting, plus anything that went wrong |
|
||||
| verbose (F8) | every line above, on the console and the serial line |
|
||||
| the klog | all of it, always, whichever of the two you booted |
|
||||
|
||||
Userspace follows the same rule through `/proc/bootmode`, which holds one word.
|
||||
`schinit`, `schinitd` and `vgpud` read it and hold back their progress lines —
|
||||
but never their failures, because a supervisor that goes quiet when a job dies
|
||||
is worse than one that chatters.
|
||||
|
||||
**`schinit` reads it after `bootstrap()` and not before**, which is the sort of
|
||||
detail that only shows up when tested: `/proc` is what `bootstrap()` mounts, so
|
||||
reading it earlier returned "quiet" every time and made the verbose boot quiet
|
||||
in the one process that runs first.
|
||||
|
||||
## What it does not do
|
||||
|
||||
- **No BIOS path.** A machine without UEFI does not boot SchOS.
|
||||
- **The quiet boot hides a slow one.** With nothing printing between the
|
||||
loader and the greeting, a boot that stalls for ten seconds looks the same as
|
||||
one that does not. F8 is the answer and it has to be pressed *before* the
|
||||
stall, which is the wrong order for finding out.
|
||||
- **`/proc/bootmode` is read once, at start.** A program that wants to be
|
||||
quieter or louder later has nowhere to say so, and nothing re-reads it.
|
||||
- **The root device is compiled in.** Booting from a USB disk needs the root
|
||||
device to be selectable, which it is not; the USB mass-storage driver works
|
||||
and a superblock reads back through `bread()`, but nothing can mount it.
|
||||
|
|
|
|||
Loading…
Reference in a new issue