Reference · Ouroboros

Glossary

The postmortems lean on a lot of low-level acronyms without pausing to explain them — reasonably, for the audience they were originally written for. This is the missing dictionary: short, plain explanations of every term used, grouped by the part of the system it belongs to, written against what this project specifically ran into rather than a generic textbook definition.

Firmware & boot CPU, memory & exceptions Interrupts & timing Storage & filesystem USB & xHCI Servers, IPC & isolation Software & toolchain

Firmware & boot

UEFI Unified Extensible Firmware Interface
The firmware standard that hands control to Ouroboros at boot. The kernel itself is built as a UEFI application — there's no separate bootloader stage — because it's the one boot path that works both on QEMU and on real Parallels hardware, which only boots ARM VMs through UEFI.
EDK2 / OVMF
EDK2 is the open-source reference implementation of UEFI firmware; OVMF is the specific build of it that QEMU boots. Several real bugs in this project trace back to EDK2's own internals — a firmware panic inside its PCI I/O driver, for instance — not to Ouroboros's code.
ESP EFI System Partition
The FAT-formatted disk partition UEFI firmware boots from. Ouroboros's kernel binary, its userland shell, and its boot config file all live here, at fixed paths like \EFI\BOOT\BOOTAA64.EFI.
Boot services / ExitBootServices
UEFI firmware exposes a set of services (memory allocation, console I/O, filesystem access) before handing full control to the OS. Ouroboros calls exit_boot_services() partway through boot and permanently leaves that environment — after which the UEFI logger, global allocator, and every UEFI protocol stop being usable.
Devicetree / DTB Devicetree Blob
A data structure describing a system's hardware — CPUs, memory, devices — as a tree, common on embedded ARM platforms. One of three console-discovery mechanisms this project tried; confirmed to not be how either QEMU or Parallels describe their hardware (both use ACPI instead).
ACPI Advanced Configuration and Power Interface
The other, more PC-style way to describe hardware to an OS, via a set of tables. QEMU and Parallels both use this instead of a devicetree. Ouroboros hand-parses a chain of these tables (RSDP → XSDT → SPCR) to find a serial console.
RSDP / XSDT
Two of the ACPI tables in that chain — the Root System Description Pointer (the very first thing found, via a UEFI config table entry) and the Extended System Description Table it points to, which in turn lists every other ACPI table present.
SPCR Serial Port Console Redirection table
The specific ACPI table that describes a platform's debug/console serial port. Present and correct on QEMU; confirmed genuinely absent from Parallels' own ACPI tables — not a parsing bug, Parallels just doesn't describe a console this way.
GOP Graphics Output Protocol
A standard, fully-specified UEFI protocol for querying a display's resolution, pixel format, and framebuffer address. This turned out to be the mechanism that actually works on real Parallels hardware, once every serial-style console option was confirmed dead — Ouroboros draws text directly into the framebuffer it reports.

CPU, memory & exceptions (AArch64)

AArch64 / ARM64
The 64-bit ARM instruction set and architecture Ouroboros targets — the same family Apple Silicon Macs use, which is why Parallels on Apple Silicon can run it without emulation.
EL0 / EL1 Exception Level
ARM's privilege-level system. EL1 is the privileged level the kernel itself runs at; EL0 is unprivileged "userland," where the loaded shell program runs. Moving between them is what the syscall boundary (svc) exists for.
MMU Memory Management Unit
The hardware that translates virtual addresses to physical ones via page tables. Ouroboros identity-maps everything (virtual address always equals physical address) but still needs real page tables — firmware's own tables get swapped out for the kernel's own right after boot services exit.
TTBR0_EL1 / MAIR_EL1 / TCR_EL1
The system registers that configure the MMU: TTBR0_EL1 points at the top of the page-table tree, MAIR_EL1 defines the available memory types (Normal vs. Device), and TCR_EL1 controls the overall translation scheme, including how many address bits are used.
T0SZ
A field inside TCR_EL1 that determines how large a virtual address range the page tables cover, which in turn determines how many table levels a lookup needs. A real bug here: switching to a table hierarchy with a different depth than firmware's own tables — even with every other bit correct — hard-faulted, until it was made to match firmware's starting level exactly.
VBAR_EL1 Vector Base Address Register, EL1
Points to the table of exception handlers. Ouroboros installs its own right after leaving boot services, so any fault from that point on is caught and reported instead of left to firmware's (no longer present) handlers.
ESR_EL1 / FAR_EL1 / ELR_EL1
The three registers read to diagnose any exception. ESR_EL1 (Exception Syndrome Register) encodes what kind of fault happened; FAR_EL1 (Fault Address Register) holds the faulting address for memory faults; ELR_EL1 (Exception Link Register) holds the address execution was at when the exception fired.
EC / DFSC / IFSC
Sub-fields inside ESR_EL1. EC (Exception Class) is the top-level category — e.g. 0x25 for a Data Abort, 0x21 for an Instruction Abort. DFSC and IFSC (Data/Instruction Fault Status Code) narrow it further — e.g. "Permission Fault" vs. "Translation Fault" vs. "Synchronous External Abort" (a real bus fault, distinct from either).
SPSR_EL1 Saved Program Status Register, EL1
Captures the processor's state (which exception level was running, interrupt masks, condition flags) at the moment an exception fires, so it can be restored on return. Part of the register set the timer-tick interrupt handler has to save and restore to correctly resume interrupted code.
TLB Translation Lookaside Buffer
A cache of recent virtual-to-physical address translations. Has to be explicitly invalidated (tlbi) whenever the page tables change, or the CPU may keep using stale mappings.
CNTPCT_EL0
The ARM generic timer's free-running physical counter — a system register that just keeps counting up in real time, readable with a plain mrs instruction, no interrupt controller or timer interrupt required. Used to fix a real bug: the USB keyboard driver's busy-waits were originally bounded by a fixed loop-iteration count instead of real elapsed time, which is only a safe stand-in for a timeout if the host never stalls the guest for any real duration mid-loop — untrue under a real hypervisor. Comparing this counter (divided by CNTFRQ_EL0, its tick rate) against a real millisecond budget fixed it.
WFE Wait For Event
An ARM instruction that parks the CPU in a low-power idle state until woken by an event or interrupt. Bit Ouroboros twice, at two different privilege boundaries: once early on, where it turned out to trap to EL1 by default instead of executing directly at EL0 (a kernel-controlled register bit, fixed once and for all); and again much later, where enabling real task-switching on real Parallels hardware hung the system the first time an idle task's wfe loop ever ran there for real — a bug one level higher than the kernel's own control, not yet fully explained, worked around by having that idle loop busy-spin instead.
SVC Supervisor Call
The instruction userland code uses to deliberately trap into the kernel — the actual mechanism behind every syscall. EL0 code puts a syscall number in a register and executes svc; the kernel's exception handler recognizes this specific case and dispatches it, rather than treating it as an error.
IRQ Interrupt Request
An asynchronous signal from hardware (the timer, in this project) that interrupts whatever's running. Unlike every other exception this kernel handles — which report and halt — an IRQ has to save full context, run a handler, and resume exactly where it left off.

Interrupts & timing

GIC Generic Interrupt Controller
The ARM hardware block that routes interrupts (like the timer tick) to the CPU. Ouroboros originally used GICv2 at addresses confirmed only by dumping QEMU's own internal devicetree — addresses later confirmed, via a real bus fault, to not exist at all on real Parallels hardware. Real ACPI MADT parsing (see below) replaced that guess with genuine platform discovery, and a GICv3 backend was added alongside the original GICv2 one, dispatched by whichever version the real hardware reports.
GICv3
A newer, architecturally different GIC generation — system-register-based CPU interface rather than memory-mapped, with per-CPU "redistributors" instead of one shared distributor for enabling a given CPU's own interrupts. Confirmed to be the real interrupt controller on Parallels via MADT discovery, and a real driver for it now works there — including real preemptive task-switching, after a separate, unrelated bug (see WFE, below) was found and fixed.
PPI Private Peripheral Interrupt
A GIC interrupt category for sources private to one CPU core, rather than shared across all of them — the generic timer's interrupt is a PPI.
INTID Interrupt ID
The numeric identifier the GIC uses for a specific interrupt source — the timer tick is INTID 30 on this hardware.
MADT Multiple APIC Description Table
The ACPI table that describes a platform's interrupt controller(s) and CPU topology — its on-disk signature is literally "APIC", the table's older x86 name, not "MADT". Now parsed by Ouroboros (madt.rs) as the genuine, portable way to discover a platform's real interrupt controller instead of guessing — confirmed working on both QEMU and real Parallels hardware, reporting completely different, correct addresses on each.
Redistributor GICR
A GICv3-specific, per-CPU memory region (distinct from the older, shared distributor) where that CPU's own private interrupts — like its own timer tick — get enabled and where the CPU must be explicitly "woken" before it will deliver anything. Finding the redistributor belonging to a specific CPU, when several may be described together, needs its own discovery walk rather than assuming the first one found is the right one.

Storage & filesystem

PCI / PCIe Peripheral Component Interconnect (Express)
The standard bus most non-trivial hardware (disk controllers, USB controllers, network cards) attaches over. Ouroboros enumerates it two different ways: a boot-services protocol during firmware, and a from-scratch config-space walk for the USB controller at runtime.
BAR Base Address Register
A PCI device's own register that reports where its control registers are mapped in memory. A real bug here: a discovered BAR address landed outside a simplifying assumption Ouroboros's own page tables had made about where every address would live.
DMA Direct Memory Access
Hardware writing to or reading from memory directly, without the CPU shuttling every byte. Both the disk and USB drivers hand devices a memory buffer and let them fill it via DMA — one debugging technique here was "poisoning" such a buffer with a known pattern beforehand to confirm a DMA write genuinely happened.
virtio
A standardized interface for paravirtualized devices — disk, network, console — designed for guests running under a hypervisor that knows it's virtualized. Ouroboros uses it for its disk driver; a virtio-console driver was also built but confirmed not to be what Parallels' console actually is.
virtio-mmio
One of two transports virtio devices can use — plain memory-mapped registers, scanned at a set of fixed addresses. The QEMU-specific convention behind one of the project's more serious real-hardware bugs: an unpopulated scan slot returns a safe default on QEMU but triggers a genuine bus fault on Parallels.
MBR / GPT
Two competing schemes for partitioning a disk. Ouroboros's FAT32 reader only understands the older MBR scheme, looking for the first FAT32-typed partition entry in it.
FAT32 / FAT16
The on-disk filesystem format Ouroboros reads and writes, hand-rolled with no external crate (every no_std FAT implementation available assumed a heap, which isn't available after boot services exit). A real gotcha: QEMU's fast dev-loop disk driver actually formats as FAT16, not FAT32 — the two look similar but aren't the same format.
LFN Long File Name
FAT's extension mechanism for filenames longer than the classic 8.3 limit. Ouroboros's reader doesn't parse these — the project's own boot-config directory had to be renamed to fit 8.3 rather than add LFN support for one avoidable case.
8.3 filename
The original FAT short-name format: up to 8 characters, a dot, up to 3 more (e.g. BOOTAA64.EFI). The only format Ouroboros's filesystem code can create or fully read.
Cluster / cluster chain
FAT32 allocates disk space in fixed-size clusters, and a file's contents are a linked chain of them recorded in the File Allocation Table. A real, silent-hang bug traced back to a FAT32 convention where cluster number zero, in a directory's ".." entry, means "the root directory" rather than a literal cluster — unhandled, it fed into an unsigned subtraction and wrapped to a garbage sector number.

USB & xHCI

xHCI eXtensible Host Controller Interface
The standard USB 3 host controller interface. Ouroboros's driver for it is the subject of the whole keyboard postmortem — command rings, an event ring, and eventually a real interrupt endpoint, all hand-rolled.
USB HID Human Interface Device
The USB device class covering keyboards, mice, and similar input devices, with its own set of class-specific requests on top of standard USB ones. A major finding: Parallels' USB passthrough doesn't forward HID class requests to the real device at all, only standard ones.
TRB Transfer Request Block
The fixed-size unit of work xHCI rings are built from — commands, transfers, and events are all TRBs, submitted and completed via producer/consumer rings in memory shared with the controller.
DCBAA Device Context Base Address Array
An array the xHCI controller reads to find each connected device's own context structure, indexed by device "slot." Part of the fixed DMA-visible memory layout the driver sets up during initialization.
ERST Event Ring Segment Table
Tells the xHCI controller where the driver's event ring lives in memory, so the controller knows where to write completion events for the driver to poll.
Configure Endpoint
A standard xHCI command (as opposed to a USB request sent to the device) that arms one of a device's endpoints for transfers. Switching to this — configuring a real interrupt endpoint instead of polling via HID class requests — was the fix for Parallels silently dropping those class requests.
Interrupt IN endpoint
A USB endpoint a device uses to push data to the host on its own schedule, rather than the host having to ask for it each time. The mechanism every production USB HID driver actually uses at runtime, and what Ouroboros switched to once class-request polling turned out not to work through Parallels' passthrough.
Setup packet
The 8-byte header that begins any USB control transfer, encoding which request is being made (bmRequestType, bRequest, wValue, wIndex, wLength). One bug's diagnosis hinged on recognizing this exact structure echoed back instead of real device data.
GET_REPORT / SET_PROTOCOL / GET_DESCRIPTOR
Specific USB requests. GET_REPORT and SET_PROTOCOL are HID class requests (confirmed not forwarded by Parallels' passthrough); GET_DESCRIPTOR is a standard request every USB device must support (confirmed to work fine) — the contrast between the two is what proved the passthrough gap was real.
bInterfaceClass / bInterfaceProtocol
Fields in a USB device's Interface descriptor identifying what kind of device it is. Class 3 is HID; protocol 1 within that is specifically Boot-Protocol Keyboard (protocol 2 is Mouse) — checking these is what let the driver tell a real keyboard apart from Parallels' virtual mouse on the same controller.
Boot Protocol
A simplified, fixed 8-byte HID report layout that keyboards and mice support for compatibility with simple BIOS/UEFI-era drivers, without needing to parse a full HID report descriptor. Ouroboros assumes this fixed layout directly rather than parsing report descriptors.

Servers, IPC & isolation

Microkernel
An OS design where drivers, the filesystem, and other services run as ordinary userland processes rather than inside the privileged kernel, so a bug in one can't corrupt the kernel or its neighbours. Ouroboros draws this from MINIX; it has moved two components out so far (the filesystem and the console).
Driver isolation
The act of moving a component out of the EL1 kernel into an unprivileged, restartable EL0 server — the concrete microkernel move. A driver that touches DMA can't be isolated safely without an IOMMU (which this platform lacks), so what moves out is pure-logic components; the kernel keeps a thin, gated hardware syscall underneath.
Server (userland)
A long-lived userland program that owns a resource and answers requests over IPC in an infinite receive → handle → reply loop. Runs in a fixed, protected task slot that can't be killed or reused by spawn.
fsd filesystem server
The FAT32 filesystem, running as a userland server (task 2). The kernel keeps only raw sector access (three block_* syscalls, accepted from this task alone); every file operation is an IPC request to fsd.
cond console server
The console, running as a userland server (task 3). Userland output flows to it over IPC; it either forwards to the kernel's byte-stream console or, on a framebuffer, renders the glyphs itself (font, cursor, wrap, scroll, ANSI) via dumb kernel pixel primitives. The kernel keeps only a minimal emergency console for boot and fault reporting.
Server supervision / heartbeat
What makes a server restartable, not just isolated (MINIX's reincarnation server / Helix's self-heal, minimal edition). The kernel keeps each supervised server's boot image and restarts it from that copy on either failure mode: a crash (the fault handler restarts any supervised task, fsd and cond alike), or a wedge — a server stuck in an infinite loop, which never faults. The wedge heartbeat is passive: a healthy server keeps returning to a blocked state, so one that stays runnable for ~2.5s is restarted on the same path. A per-boot restart cap degrades gracefully past it. Confirmed live on real Parallels hardware for cond.
IPC inter-process communication
How isolated tasks talk: by copied messages through the kernel, never shared memory — the isolation-friendly semantics. A message goes straight into a waiting receiver's buffer, or into a small bounded mailbox.
msg_call / sendrec
The synchronous request/reply IPC primitive (MINIX's sendrec shape): send a request to a server and block for its reply specifically. The kernel switches straight to the destination server so the round trip completes without waiting for a scheduler tick.
Capability model / send-mask
Who-may-call-whom, enforced. Beyond memory isolation, each task has a per-slot send-mask — the set of endpoints it may initiate IPC to — checked at the msg_send/msg_call boundary, so a spawned program can reach only the two servers and the shell, not arbitrary tasks or the privileged device gates. A reply to a caller blocked in a call is always allowed (so servers reply freely). Because task roles are static, the whole policy is a pure function of slot — no stored state. Isolation is topological, not just memory-level; MINIX's send masks in miniature. Static for now (no runtime delegation).
grant / safecopy
A capability-based way to move bulk data between two isolated tasks (messages are small). A client grants a server permission to copy an exact buffer, in one direction, only while its call is live; the kernel enforces the server can touch only those bytes. This is MINIX's safecopy.
Per-task page tables
Each scheduler slot runs under its own MMU translation-table view: identical kernel/device mappings, but EL0 access to that task's own memory alone. Touching another task's memory faults — isolation enforced by hardware, not convention. Proven by fault injection.

Software & toolchain

PE/COFF Portable Executable / Common Object File Format
The executable format UEFI applications use (yes, the same family as Windows .exe files). Ouroboros's kernel builds as one. A real toolchain quirk here: this backend only infers "executable" section characteristics for exactly-recognized section names, not custom ones with a matching prefix — the root cause of one exception-vector bug.
ELF Executable and Linkable Format
The executable format most Unix-like systems use, with built-in support for relocations. Ouroboros's userland programs are not ELF — they're flat binaries with no relocation processing, which is the direct cause of the project's most-repeated bug (see "relocation" below).
Relocation
The process of adjusting a binary's internal addresses to match where it actually ends up in memory, since it was compiled assuming some fixed base address. Ouroboros's userland loader does none of this, which means any compiled-in pointer to data (a formatting-macro dispatch table, a string literal being compared against) is silently wrong once loaded — the single most repeated bug class across the shell/filesystem work.
POSIX
A family of standards for Unix-like operating system interfaces. Ouroboros's design goal is "POSIX-ish" system calls — familiar in shape, not a strict compatibility target.
Syscall ABI
The contract between kernel and userland for making system calls — which register holds the syscall number, which holds arguments, where the return value goes. Ouroboros uses Linux's general convention (number in a dedicated register, arguments following) without aiming for actual Linux binary compatibility; the numbers and sentinel values themselves live in a small shared crate both sides depend on.
no_std
A Rust program built without the standard library — no heap-backed collections, no OS-provided I/O — because there's no OS underneath to provide them. Both the kernel and its userland shell are no_std; the kernel additionally loses even its (boot-services-backed) heap the moment it exits boot services.
core::fmt / write!
Rust's formatting machinery, still available under no_std — and the specific thing that turned out to crash any of Ouroboros's loaded userland programs, since it builds its argument-dispatch table as compiled-in pointer data, which relocation (see above) never fixes up.