Skip to content
Back to work

ChronoOS

repository: chronosapien

A hobby operating system written in Rust.

State
Active
Category
Systems
Year
2026
Role
Solo
Deployment
Local onlyRuns locally in QEMU
ChronoOS boot path
  1. Firmware / QEMU

    loads the bootable image

  2. Bootloader

    long mode, paging, framebuffer + memory map

  3. Kernel entry

    no_std Rust, serial before pixels

  4. Interrupts + memory

    GDT, IDT, PIC, PIT, free-list heap

  5. ChronoFS

    ATA PIO, fsck, repair, journal

  6. Shell + apps

    commands, eras, notes, calc, sysinfo

ChronoOS is a hobby operating system in Rust. It boots a no_std x86_64 kernel under QEMU, brings up its own framebuffer console, and drops you into a shell. I started it because I had spent years building on top of abstractions I could not describe, and the fastest way to fix that was to write the layer underneath one of them.

Why

Most of my work sits several layers above the machine. A request arrives, a framework routes it, a runtime schedules it, a kernel actually does it. I could describe the first two layers precisely and the last one only in outline, which is an uncomfortable thing to notice about your own stack.

ChronoOS is the correction. It is not trying to be Linux and it is not going to run your servers. It is a small, readable teaching OS where every layer between power-on and a blinking cursor is something I had to write and can therefore explain.

Boot flow

The path from a frozen QEMU window to an interactive prompt runs through ten steps, and each one can fail in a way that looks identical from the outside: a black screen.

  • QEMU emulates an x86_64 machine and loads the bootable image.
  • The bootloader puts the CPU into long mode and sets up paging.
  • Handoff passes the kernel two things it cannot work without: a framebuffer pointer and a memory map.
  • Kernel entry jumps into the Rust no_std entrypoint. Everything after this line is the operating system.
  • Serial comes up first, deliberately, because it is the only output path that works when graphics do not.
  • Framebuffer console starts writing glyphs, pixel by pixel. This is the first moment the thing looks like an OS.
  • GDT and IDT load, so the CPU knows what to do on a fault or an interrupt.
  • The PIT starts ticking, which is where time begins.
  • Keyboard IRQs are enabled and scancodes start becoming characters.
  • The shell loop begins polling and dispatching. The OS is now interactive.

Bringing serial up before anything visual is the single decision that made the rest tractable. A blank screen is not a failure signal, it is the absence of one, and the fix is always to make the machine talk to you earlier than the thing you are debugging.

What is in the kernel

The kernel is around thirty modules. The ones that carry the most weight:

  • Memory - memory-map helpers and a free-list heap, so allocation is something the OS does rather than something it inherits.
  • Interrupts - GDT, IDT, PIC, and PIT wiring, with CPU exception handlers that print something useful instead of triple-faulting.
  • ChronoFS - the largest single module, with an ATA PIO backend, fsck, a repair path, and a small journal.
  • Shell - by far the biggest file in the repository, because it doubles as the product surface: categorised help, onboarding, era themes, museum pages, quests, and status screens.
  • Apps - a static registry with notes, calc, and sysinfo, running against a defined app boundary rather than reaching into the kernel.
  • Teaching paths - a cooperative scheduler, Ring 3 demos, syscalls, static ELF loading, early SMP, and a static IPv4 ARP/UDP stack.

Implemented is not verified

The most useful thing I did on this project was not a feature. It was splitting every claim into two columns: implemented in code and verified at runtime. The repository carries a verification matrix that records, per system, what level of evidence exists and what is still missing.

That split is unflattering by design. Single-core BIOS boot reaching [CHRONO] boot completeis verified, with serial logs and framebuffer screendumps. Typed input in QEMU, including Backspace and Shift, is verified. An unattended harness types 52 shell commands over the serial port and checks each one's output, including a full ChronoFS session on a throwaway disk: write, copy, search, delete, and a clean fs check. RTL8139 initialisation and its MAC address have evidence.

ChronoFS writes surviving a reboot, general userspace, ARP and UDP behaviour, most of the mouse and window paths, UEFI, the custom BIOS handoff, and application-processor startup are written but not yet proven at runtime. TCP, DHCP, DNS, USB, a dynamic linker, a package manager, and a real preemptive scheduler are design-only.

It would be easy to write "networking" on a feature list. It is more useful, and more honest, to write "an RTL8139 driver that initialises and reports its MAC, with ARP and UDP code that has not been observed working."

Hard problems

  • Observability before features. Every early bug presented as a black screen. The fix was always to move the debugging surface earlier in the boot, not to stare harder at the code that came later.
  • Text without a text renderer. A framebuffer gives you pixels. Getting readable characters means glyph rendering and a console abstraction before you can print your first error message.
  • A kernel bug I blamed on the emulator. From June to October typed commands came out with doubled letters, as in woorrkssppaacee, and I logged it as a QEMU quirk. It was the keyboard interrupt handler reading port 0x60 without checking the status port first. When the polling path had already taken the byte, QEMU handed back the same one again.
  • SMP is where confidence goes to die. Two-core smoke testing reached the bootstrap processor and no further. It is marked partially implemented and risky, because that is what it is.
  • Keeping the docs from drifting. A teaching OS whose documentation overstates it is worse than no teaching OS. Several commits in this repository do nothing but re-audit the status tables against the source.

Current state and what is next

v0.3 is about verification rather than new features. The next step is running the serial smoke harness on every kernel change, and growing it to cover the remaining read-only commands and a reboot step that proves ChronoFS writes persist.

After that, the order is window and input lifecycle, filesystem repair and recovery, userspace, and only then UEFI, SMP, networking, and real hardware.

Have an interesting problem?

I am most useful on the ones that cross a boundary: a product decision that turns out to be a data-model decision, or a bug that only reproduces in production. If that sounds like yours, I would like to hear about it.

vanshajpoonia06@gmail.com