The `system` module (formerly `danos`) had become a grab-bag: it held the
loader<->kernel handoff *and* the kernel<->user ABI *and* the device wire types, in
one module three different audiences imported. Usage proved the seam — the
bootloader never touched the syscall/device ABI, and user space never touched the
boot handoff — so split it by audience, one module per contract:
system/boot-handoff.zig loader <-> kernel: BootInformation, Framebuffer,
MemoryMap, the VM layout + physicalToVirtual, kernel_abi
system/abi.zig kernel <-> user, core: SystemCall, mmap prot flags,
page_size, notify_badge_bit, ServiceId
system/devices/device-abi.zig kernel <-> user, devices: DeviceDescriptor,
DeviceClass, ResourceDescriptor, ResourceKind, ...
device-abi is the devices sub-project's public interface, exposed as its own module
the way vfs exposes vfs-protocol — importable by user space, unlike the
kernel-internal device model it also feeds. That collapses a real duplication:
DeviceClass and ResourceKind were defined twice (device-model.zig and the contract,
kept "in sync by hand"); device-model now re-exports them from device-abi, so the
enum a driver matches on and the one the kernel classifies with are one type.
Each import now declares which contract it speaks: the bootloader imports only
boot-handoff; a driver only abi + device-abi (via the runtime); the kernel all
three. This also retires the `system` / `runtime.system` name overlap. page_size
lands in abi (it's part of the mmap contract user space aligns to); the bootloader
keeps its own local 4 KiB constant so it depends on nothing but the handoff.
All 21 importers rewired, docs updated to keep /system mapping to source. Build,
host tests, and the QEMU suite (36/36) all green.
69 lines
2.7 KiB
Markdown
69 lines
2.7 KiB
Markdown
# DanOS
|
|
Codename: Shodan
|
|
Version: 1
|
|
|
|
A small operating system, written from scratch in Zig — a bootloader (`boot/`)
|
|
and a microkernel (`system/kernel/`), sharing a neutral handoff contract (`system/boot-handoff.zig`).
|
|
It boots x86-64 via UEFI, and so far has a framebuffer console, a physical frame
|
|
allocator, its own paging with W^X permissions, interrupt/exception handling, a
|
|
LAPIC timer, a kernel heap, a fixed-priority preemptive scheduler, and in-kernel IPC
|
|
channels. See [`docs/`](docs/README.md) for how each piece works.
|
|
|
|
## Prerequisites
|
|
|
|
- **Zig 0.16.x** — the build is pinned to this line (`.zig-version`); other minor
|
|
versions are rejected, because Zig makes breaking changes between releases
|
|
pre-1.0. A toolchain manager such as [zvm](https://github.com/tristanisham/zvm)
|
|
or `zigup` will pick up `.zig-version` automatically.
|
|
- **QEMU** (`qemu-system-x86_64`) — to run and test the kernel. On macOS,
|
|
`brew install qemu` also bundles the OVMF firmware below.
|
|
- **OVMF** UEFI firmware — the `edk2-ovmf` package (Arch), `ovmf` (Debian/Ubuntu),
|
|
or `edk2-ovmf` (Fedora); on macOS it ships inside the Homebrew `qemu` formula.
|
|
Both the build and the test harness probe the known Arch/Debian/Fedora/macOS
|
|
layouts and use the first that exists, so no configuration is normally needed.
|
|
Override with `-Dovmf-code=` / `-Dovmf-vars=` (build) if yours lives elsewhere.
|
|
- **Python 3** — for the QEMU integration test harness.
|
|
|
|
## Build
|
|
|
|
```sh
|
|
zig build
|
|
```
|
|
|
|
Produces a FHS-shaped `zig-out/` that *is* the danos filesystem and the boot volume:
|
|
the UEFI bootloader at `zig-out/EFI/BOOT/BOOTX64.efi`, the kernel at
|
|
`zig-out/system/kernel`, init at `zig-out/system/services/init`, drivers under
|
|
`zig-out/system/drivers/`, and the initial-ramdisk at `zig-out/boot/`.
|
|
|
|
## Run
|
|
|
|
Boot it in QEMU with OVMF (opens a display window):
|
|
|
|
```sh
|
|
zig build run-x86-64
|
|
# distro with OVMF elsewhere:
|
|
zig build run-x86-64 -Dovmf-code=/path/OVMF_CODE.fd -Dovmf-vars=/path/OVMF_VARS.fd
|
|
```
|
|
|
|
## Test
|
|
|
|
```sh
|
|
zig build test # host unit tests (the platform-independent shared code)
|
|
python3 test/qemu_test.py # QEMU integration tests: boots the kernel and asserts
|
|
# on its serial output (see docs/testing.md)
|
|
```
|
|
|
|
The integration harness builds and boots the kernel once per test case, checking
|
|
memory, the frame allocator, paging (incl. NX and the null guard), the heap,
|
|
interrupts, and exception handling. It exits non-zero on any failure, so it drops
|
|
straight into CI.
|
|
|
|
## Documentation
|
|
|
|
Design notes explaining the *why* behind the code live in
|
|
[`docs/`](docs/README.md) — start with [`docs/README.md`](docs/README.md).
|
|
|
|
## Logo
|
|
|
|
San Serif Text "Dan OS" with a black karate belt around it.
|