The CLS_BUS seam lands today, completing the five-contract Hardware Abstraction Layer that governs how sigilOS binds real hardware drivers. Every device class — input, storage, USB, power management, and now PCI bus — has a defined kernel-side contract: a fixed function signature, a capability gate, and a QEMU-verifiable model. Real silicon plugs in; the kernel doesn't change.
The contract pattern
Every HAL seam uses the same structure. The kernel side defines a routing function:
bus_route(id, op, a0, a1, a2, need)
Where id is the bound driver slot, op is the operation code, a0–a2 are operation-specific arguments, and need is the required capability. Before doing anything, bus_route checks cap_check(need). If the caller doesn't hold CAP_BUS, it returns E_PERM immediately — no operation is performed, no state is read, no address is touched.
This is the same pattern as power_route (CLS_POWER) and every other HAL seam. The capability check is not a suggestion — it is the first instruction in the dispatch path.
The driver side implements three functions:
bus_cfg_read(bdf, offset)— read a PCI configuration registerbus_cfg_write(bdf, offset, val)— write a PCI configuration registerbus_map_bar(bdf, bar_idx)— return the base address of a PCI BAR
Three real backends exist: AArch64 ECAM (memory-mapped config space), x86 CF8/CFC port-I/O, and I²C SMBus. All three implement the same three functions. The kernel doesn't know which one is bound — it calls through the HAL and gets the right answer.
CLS_BUS in detail
core/bushal.sg defines the kernel-side dispatch. modules/busmodel.sg is the QEMU-side model: a 4-entry PCI config table at 0x3C0000, each entry holding bdf, vid:did, command:status, class:rev, BAR0, and BAR1. This is enough to smoke-test every HAL operation without real PCI hardware:
| Test step | What it verifies | Result |
|---|---|---|
| init | Add 2 simulated PCI devices to the bus model | init=1 |
| cfg_read | Read vid:did and class:rev from device 0 | read=1 |
| cfg_write | Write command register, read back to confirm round-trip | write=1 |
| map_bar | Retrieve BAR0 and BAR1 base addresses | bar=1 |
| cap gate | Call with wrong capability → E_PERM, no read performed | gate=1 |
Serial output: BUS init=1 read=1 write=1 bar=1 gate=1 K PASS.
Why five contracts, why now
A traditional kernel HAL is implicit — the kernel calls into driver code that was compiled against a set of headers. There's no runtime check that the driver implements the right interface, and nothing stops a driver from calling back into kernel internals it wasn't supposed to touch.
sigilOS's HAL contracts make the interface explicit and the boundary enforceable:
- Explicit: each contract names exactly three to five functions the driver must implement. The kernel calls nothing else.
- Capability-gated: every dispatch path checks the caller's capability before proceeding. A driver that misbinds to the wrong class gets
E_PERM, not a crash. - Model-backed: each seam ships with a silicon-free QEMU model. A new driver can be developed and tested against the model before any real hardware is involved.
- First-def-wins replaceable: the model implementation uses the same first-def-wins override pattern as every other Sigil module. Linking the real driver before the model replaces it transparently — the kernel code and the test suite are unchanged.
The five contracts cover every hardware class the 0.6.0 milestone requires. Input handles HID from USB keyboards, mice, and Bluetooth game controllers. Storage handles the block layer for FAT, NTFS, and the FS stack. USB host handles the xHCI and dwc2 controllers that enumerate the device tree. Power handles PSCI (AArch64) and ACPI (x86) for suspend/resume and shutdown. Bus handles PCI config space and I²C, which is the discovery mechanism for everything that isn't USB.
What's next
The HAL contracts are kernel-side seams — they define what the kernel expects. The Drivers repo (sigil-drivers) is where the real implementations live. The USB UHCI control schedule and device enumeration have already landed (504022a). The remaining 0.6.0 driver work is OHCI and UVC (camera). Both can now develop against a defined contract with a QEMU model that proves compliance before any hardware is touched.