Milestone 1 of three: manifests, RunAtLoad, KeepAlive with throttling,
and reaping. Replaces the hardcoded fork-a-shell loop in cmd/init, which
stays in the tree for now.
Jobs are sectioned key=value files in /etc/schinit/*.job, kept in the
repo under etc/ and installed into the sysroot -- sysroot/ is generated
and gitignored, so anything written only there is lost on a fresh clone,
which is already true of /etc/passwd and should not become true of the
boot configuration. Unknown keys and sections are ignored rather than
fatal: a manifest written for a newer schinit must not stop this one
booting the machine.
Socket sections are parsed and recorded but not yet held. That is
milestone 2 and it is the whole reason for copying launchd rather than
sysvinit -- the supervisor holds the listener and starts the job on first
connect, which inverts the dependency graph and makes runlevels a
non-concept. The key exists now so manifests need not change later.
getdents64 is exposed to userland for this. The kernel has had it since
the Linux ABI landed, but nothing declared it in user.h or lib/usys.S, so
first-party programs had no way to list a directory at all.
Two things found by testing rather than reasoning:
- setsid() gives a job its own session, and a session has no
controlling terminal. The console then delivers input only to the
foreground process group it tracks, so the shell came up, echoed
every keystroke through the line discipline, and executed none of
them -- indistinguishable from a hung shell. ControllingTerminal=yes
claims it with TIOCSCTTY/TIOCSPGRP; off by default, since a daemon
has no business seizing the console.
- the first bootstrap() dropped /dev/input/event0-1 and most of /proc,
because it was transcribed from the part of the old init that had
been read rather than all of it. -Evdev caught it.
build/usbstick.img is built by `all` now: without it QEMU refuses the
-drive and the entire -Usb run produces no output, which reads as a
broken USB driver.
Seven suites green: base 27, Tty 51, Ps 32, Sock 64, Fb 36, Usb 31,
Evdev 29. make schfs-check passes.
49 lines
2.6 KiB
Markdown
49 lines
2.6 KiB
Markdown
---
|
|
name: schunix-iso-boot
|
|
description: "`make iso` builds a bootable CD; it needs El Torito no-emulation plus ATAPI because the loader never uses INT 13h"
|
|
metadata:
|
|
node_type: memory
|
|
type: project
|
|
originSessionId: a665e14b-86bd-4b41-a228-51377f3e9225
|
|
modified: 2026-08-04T17:28:16.714Z
|
|
---
|
|
|
|
**`make iso` produces a bootable `schunix.iso`** (added 2026-08-04). Always a
|
|
RAMROOT build — a disc that needed a second disk for its root would not be an
|
|
install medium, and read-only media cannot host a writable root anyway.
|
|
|
|
**Why it is built the way it is.** Schunix's loader never calls INT 13h: it
|
|
drives the IDE registers directly, and stage2 has already switched to
|
|
protected mode before it reads the kernel. That rules out both El Torito
|
|
emulation modes (hard-disk emulation exists only through the BIOS) and floppy
|
|
emulation (2.88 MB cap). So:
|
|
|
|
- `boot/cdboot.S` — a separate stage 1 for optical media. `tools/mkiso.sh`
|
|
passes `-boot-load-size 25`, so the BIOS loads cdboot *and* all 24 sectors of
|
|
stage2 before anything of ours runs, putting stage2 at 0x7E00 exactly where
|
|
`bootasm.S` would have. cdboot only records the medium and jumps.
|
|
- The medium flag is one byte past the verbose flag, at `VBE_INFO_ADDR + 0x101`.
|
|
**`bootasm.S` must clear it** or a warm reboot from a disc sends a hard-disk
|
|
boot looking for an optical drive.
|
|
- `stage2main.c` gained an ATAPI reader (PACKET + SCSI READ(12), 2048-byte
|
|
blocks with a one-block cache) and finds where it was loaded from by reading
|
|
the El Torito boot catalog: LBA 17, pointer at offset 0x47, then Load RBA at
|
|
catalog offset 40.
|
|
- **Do not pass `-boot-info-table`** to xorriso — it patches 56 bytes over
|
|
offset 8 of the boot image, which is the middle of cdboot's code. That is
|
|
why the boot catalog is parsed instead.
|
|
|
|
**The trap that cost the most time here:** ATAPI's 0x14/0xEB signature is only
|
|
valid until something issues a command, and the BIOS has just finished reading
|
|
the disc to load us — so on a CD boot the signature is *always* stale.
|
|
`atapi_reset()` (SRST via the control port at `io + 0x206`) is what makes the
|
|
probe work.
|
|
|
|
Two unbounded waits were hiding behind that, both of which hung with no
|
|
message on a machine with no ATA disk: `waitdisk()` in stage2main.c and
|
|
`idewait()` in kernel/dev/ide.c. Both are bounded now, `ideinit()` tolerates an
|
|
empty channel, and anything that *probes* a disk must call
|
|
`ide_disk_present()` first — `iderw()` rightly panics on an absent drive.
|
|
|
|
Check it with `pwsh -File tools/bootcheck.ps1 -Iso -Fb`, which boots with no
|
|
hard disk attached at all. See [[schunix-verify-by-driving-shell]].
|