bug pass: whole console lines, a quiet SCI, an honest reserve warning

- schinit, schinitd and vgpud build every message from pieces, one
  write() each, so a job starting on another CPU landed mid-line:
  "schinitd: starting vgpud: os.schos.resolvconfno virtio-gpu on this
  machine". They now collect a line and write it at the newline;
  resolvconf's verbose line is one write with its prefix.
- The ACPI SCI registers IRQ_QUIET. A desktop's SCI never fires, and the
  poller took two seconds of silence for a misrouted line ("irq 9:
  nothing has arrived on it") and called the handler every tick. A line
  is only exempt while every handler on it is quiet.
- The loader claims each segment from where the last one's claim ended,
  so two segments sharing a page no longer ask for it twice. When a
  claim is still refused, it names the memory-map entries in the way.
- Stale divesymlink() declaration gone; the kernel.md struct table
  re-measured (inode, buf and file pools grow from slabs now).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-23 16:03:33 +02:00
commit e659c6b187
10 changed files with 184 additions and 25 deletions

View file

@ -90,6 +90,7 @@ static EFI_BOOT_SERVICES *BS;
static void mirrors_show(void); /* see "the other displays", further down */
static void mirrors_match(EFI_GRAPHICS_OUTPUT_PROTOCOL *primary);
static void describe_gop(EFI_GRAPHICS_OUTPUT_PROTOCOL *g, const CHAR16 *tag);
static void explain_range(UINT64 lo, UINT64 hi);
/* Once the splash is up, nothing may write to the console.
*
@ -522,6 +523,8 @@ load_elf(EFI_FILE_PROTOCOL *file)
}
ui_progress_begin("Loading SchOS", (ui_u32)(total ? total : 1));
EFI_PHYSICAL_ADDRESS claimed_end = 0; /* see the AllocatePages below */
for (UINT16 i = 0; i < eh.e_phnum; i++) {
struct elf64_phdr ph;
n = sizeof ph;
@ -537,9 +540,23 @@ load_elf(EFI_FILE_PROTOCOL *file)
// and this is its memory until it says otherwise; writing to
// conventional memory it has not handed over is how a loader corrupts
// the very services it is about to call.
EFI_PHYSICAL_ADDRESS at = ph.p_paddr & ~0xfffULL;
UINTN pages = (UINTN)((ph.p_paddr + ph.p_memsz - at + 0xfff) / 0x1000);
st = BS->AllocatePages(AllocateAddress, EfiLoaderData, pages, &at);
//
// From the end of what the previous segment claimed, not from this
// one's first page. The linker packs segments without page-aligning
// them -- .text ending at 0x1dc9fe and .rodata starting at 0x1dca00 --
// so two segments routinely share a page, and asking for that page a
// second time is refused because it is ours already. That was the
// "could not reserve" warning on every boot, about memory that was
// reserved all along.
EFI_PHYSICAL_ADDRESS at = ph.p_paddr & ~0xfffULL;
EFI_PHYSICAL_ADDRESS end = (ph.p_paddr + ph.p_memsz + 0xfff) & ~0xfffULL;
if (at < claimed_end)
at = claimed_end;
UINTN pages = at < end ? (UINTN)((end - at) / 0x1000) : 0;
st = pages ? BS->AllocatePages(AllocateAddress, EfiLoaderData, pages, &at)
: EFI_SUCCESS;
if (end > claimed_end)
claimed_end = end;
if (EFI_ERROR(st)) {
// Already allocated by the firmware for something of its own, or
// simply not conventional memory. Not fatal on its own -- the
@ -547,6 +564,7 @@ load_elf(EFI_FILE_PROTOCOL *file)
// that boots and then corrupts itself starts here.
print(L"schos: warning: could not reserve "); print_hex(at);
print(L"\r\n");
explain_range(at, end);
}
if (ph.p_filesz) {
@ -1044,6 +1062,32 @@ map_read(UINTN *size, UINTN *key, UINTN *dsize, UINT32 *dver)
key, dsize, dver);
}
/* Who owns [lo, hi), when it was not ours to take.
*
* "could not reserve" alone says where and not why, and the why decides
* whether it matters: boot-services memory is the firmware's until
* ExitBootServices and harmless to overwrite after it, while runtime services
* or ACPI tables under the kernel are a machine that will corrupt itself. So
* every descriptor in the range that is not free memory is named. */
static void
explain_range(UINT64 lo, UINT64 hi)
{
UINTN size, key, dsize;
UINT32 dver;
if (EFI_ERROR(map_read(&size, &key, &dsize, &dver)) || !dsize)
return;
for (UINTN off = 0; off + dsize <= size; off += dsize) {
EFI_MEMORY_DESCRIPTOR *d = (EFI_MEMORY_DESCRIPTOR *)(mapbuf + off);
UINT64 a = d->PhysicalStart, b = a + d->NumberOfPages * 4096;
if (b <= lo || a >= hi || d->Type == EfiConventionalMemory)
continue;
print(L"schos: type "); print_dec(d->Type);
print(L" at "); print_hex(a); print(L".."); print_hex(b);
print(L"\r\n");
}
}
static UINT64
memory_mb(void)
{