console: put the kernel log on screen from the first line
Everything the kernel printed went to the serial port and nowhere else until the first program started and called console_takeover(). On a machine with a UART that is fine. On one without -- a laptop, a Chromebox, anything built this century -- the screen showed the loader's progress bar and then nothing at all, for the whole of boot, on exactly the machines where something was going wrong. A report of "it shows Loading SchOS and freezes" cannot be acted on. The same boot with a log on it says which line it stopped after, and that is usually the whole diagnosis. The loader has already put a framebuffer on the screen and described it in the boot block, so there was a perfectly good console sitting unused for the entire early boot. kmain attaches it on its first line now. Not gated on the F8 verbose menu, which was the first instinct and is wrong: F8 is no use to someone whose machine resets before they can read anything. This is what Linux does too -- the log is the default and `quiet splash` is the thing you ask for. The splash survives until the kernel's first message, and a boot that succeeds clears the lot when the shell starts, so the only people who ever see this are the people who need to. vt_init is idempotent now, because the early attach brings the terminals up before main() reaches its usual call and the second one must not wipe six screens of boot messages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
This commit is contained in:
parent
52e6e9b756
commit
7d44eb75a3
2 changed files with 50 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#include "types.h"
|
||||
#include "defs.h"
|
||||
#include "vt.h"
|
||||
#include "gfx.h"
|
||||
#include "param.h"
|
||||
#include "memlayout.h"
|
||||
#include "mmu.h"
|
||||
|
|
@ -31,6 +32,46 @@ kmain(uint32 fb_addr)
|
|||
{
|
||||
boot_verbose = *(uchar*)P2V(SCHBOOT_VERBOSE_FLAG);
|
||||
|
||||
// On a verbose boot, put the kernel log on the screen from the first line.
|
||||
//
|
||||
// Everything below talks to the serial port and nothing else until the first
|
||||
// exec calls console_takeover(). That is fine on a machine with a UART and
|
||||
// useless on one without -- and a laptop, a Chromebox, anything built this
|
||||
// century has no 16550 at 0x3f8. The screen showed the loader's progress bar
|
||||
// and then nothing at all, for the whole of boot, on exactly the machines
|
||||
// where something was going wrong.
|
||||
//
|
||||
// The loader has already put a framebuffer on the screen and described it in
|
||||
// the boot block, so there is a perfectly good console sitting there unused.
|
||||
// Attaching it here costs one struct and makes the difference between "it
|
||||
// froze" and knowing which line it froze after.
|
||||
//
|
||||
// Unconditional, not just on a verbose boot. F8 is no use to someone whose
|
||||
// machine resets before they can read anything, and "it froze after the
|
||||
// loading bar" is a bug report nobody can act on. This is what Linux does
|
||||
// too: the log is the default and `quiet splash` is the thing you ask for.
|
||||
//
|
||||
// The splash stays on screen until the kernel's first message, and a boot
|
||||
// that succeeds clears the whole lot when the first program starts -- so
|
||||
// the only time anyone sees this is the only time anyone needs it.
|
||||
{
|
||||
struct fb_info bi;
|
||||
bi.ptr = (volatile uchar *)P2V((uint64)*(uint32*)P2V(SCHBOOT_VBE_LFB));
|
||||
bi.width = *(uint16*)P2V(SCHBOOT_VBE_WIDTH);
|
||||
bi.height = *(uint16*)P2V(SCHBOOT_VBE_HEIGHT);
|
||||
bi.stride = *(uint16*)P2V(SCHBOOT_VBE_STRIDE);
|
||||
bi.bpp = *(uchar *)P2V(SCHBOOT_VBE_BPP);
|
||||
// Only if the loader actually described something. A zero here means the
|
||||
// BIOS path or a firmware that gave no GOP, and drawing into address zero
|
||||
// is a worse failure than staying quiet.
|
||||
if (bi.ptr && bi.width && bi.height && bi.stride && bi.bpp >= 16) {
|
||||
gfx_attach_scanout(&bi);
|
||||
vt_init();
|
||||
gfx_clear(0x0C0E13); /* SCH_BG; theme.h is not included here */
|
||||
cons_serial_only = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uartearlyinit();
|
||||
if (boot_verbose) cprintf("verbose boot: uartearlyinit done\n");
|
||||
// The DMA arena is carved off the top of physical memory *before* kalloc is
|
||||
|
|
|
|||
Loading…
Reference in a new issue