← Back to selected work

SYSTEMS ENGINEERING · ACTIVE EDUCATIONAL KERNEL

An operating system built from the boot handoff upward.

CharisOS is a from-scratch x86_64 kernel written in C and NASM. It is a hands-on way to work with boot flow, memory, interrupts, scheduling, syscalls, filesystems, and the boundary between kernel and user mode.

Role · Design & engineeringStack · x86_64 · C · NASM · Multiboot2 · GRUB2 · QEMUSource · GitHub ↗
Public CharisOS repository and documentation screenshot
Public CharisOS repository and documentation screenshot. The image is a project/repository screenshot, not a fabricated interface mockup.
~9,100lines of C across 107 files
~720lines of NASM across 6 files

The problem

Frameworks hide a lot of what a computer is doing. CharisOS is a learning project that moves below the application layer: start at the GRUB handoff, enter long mode, and build the kernel facilities that applications eventually depend on.

Constraints

The kernel is freestanding: it builds with gcc -ffreestanding, uses a hand-written linker script, and does not depend on libc or a host operating system at runtime.

That means basic facilities normally taken for granted have to be implemented and exercised directly. Compiling is not enough; a subsystem is only marked complete when it has been booted and tested.

What I built

  • Multiboot2 and GRUB2 boot flow into x86_64 long mode.
  • Physical and virtual memory management, a kernel heap, and per-process address spaces.
  • IDT/IRQ handling, a PIT timer, keyboard and serial paths, and kernel-task scheduling.
  • A virtual filesystem with a FAT32 read path and a static ELF executable loader.
  • A ring-3 bootstrap that enters user mode, performs a syscall, yields, and resumes in QEMU tests.
  • A framebuffer graphics and window-manager stack that remains partial.

Decisions and trade-offs

Keep the kernel freestanding. This exposes the real interfaces and failure modes, but means there is no libc or mature userland to lean on.

Use executable smoke tests. Booting and exercising a path is stronger evidence than marking a feature complete because it compiles.

Track partial subsystems honestly. The repository distinguishes working paths from configured-but-unvalidated or incomplete ones, including the fast syscall path, networking, and parts of the desktop stack.

The hard part

The difficult part is not a single isolated function. It is keeping boot, memory, interrupts, scheduling, and user-mode transitions consistent enough that a real execution path survives. The current ring-3 test is valuable because it crosses several of those boundaries in one flow.

Outcome

The repository's CI verifies BIOS CD and raw-disk boot paths, including a ring-3 syscall and yield/resume round trip. UEFI boot paths have passed locally; UEFI CI remains advisory. The codebase and status document are public.

Recorded boot walkthroughs: Part 1 ↗ · Part 2 ↗.

This is an active educational kernel, not a complete consumer operating system. Userland/libc has not started, and several networking, USB, audio, and desktop components remain partial or stubbed.

What I'd build next

The next major milestone is a more complete userland path: finish the boundaries around ELF loading and address spaces, then begin libc and ordinary user programs. I would keep the same rule for every milestone: test the behavior before calling it complete.