mathieu.brebion
All projects
Personal Project — Operating System From Scratch

BrebOS

A hand-built operating system for x86, written mostly in C++ — with its own compiler, C/C++ standard library, network stack, and shell. Assembly only shows up where the hardware leaves no other choice: boot, interrupts, context switches.

Since 2024 · Mostly C++ · Solo project

Origin

Third time's the charm

BrebOS was my third attempt at writing an operating system. The first two stalled — I simply didn't have the knowledge yet, and most tutorials I found were either too shallow or out of date. What finally got me unstuck was The Little Book About OS Development by Erik Helin and Adam Renberg: written for people who already know C and a bit of assembly, it explains everything carefully at first, then hands over more and more of the work as exercises, pointing out the pain points instead of spelling out every line. I was also on academic exchange in Seoul at the time, taking an OS class whose syllabus tracked closely with what I was building — I implemented each topic around the same time the class covered it, sometimes finishing a bit later when a given week didn't leave enough time.

Once I'd worked through the book, I was on my own: the OSDev wiki, the ELF specification, and the FAT32 specification became my main references for everything that came after — paging, the scheduler, the filesystem, ELF loading, the network stack, and the rest.

37k+
lines of code, mostly C++
420+
commits since May 2024
2024
in development, on and off, since
x86
32-bit protected mode, own bootloader
Architecture

From bare metal to your own program

Every layer between the CPU and a shell prompt is BrebOS's own — including the compiler that builds it.

  1. 05Userland

    42sh, a handful of BrebOS's own native programs (mkdir, touch, wget, and more), and real BusyBox binaries — ls, cat, and others — cross-compiled with BrebOS's own toolchain and running unmodified. Add your own C++ program just as easily, with the STL, RTTI, and exceptions all working.

  2. 04Toolchain & runtime

    A hosted GCC cross-compiler (i686-brebos-gcc) aware of BrebOS's internals, a ported mlibc and libstdc++-v3, and a dynamic linker doing lazy symbol resolution for ELF binaries.

  3. 03Drivers & subsystems

    A from-scratch USB driver (xHCI, Bulk-Only Transport, and the SCSI commands underneath) is BrebOS's primary storage path today, with an ATA driver kept as a fallback — both sit behind the same FAT32 filesystem and VFS abstraction. Alongside them: a PS/2 keyboard driver and an E1000 network stack running Ethernet, ARP, IPv4, UDP, ICMP, DHCP, and a still-thin TCP up to a working HTTP GET.

  4. 02Kernel core

    GDT, IDT, PIC remapping, paging, a lazy allocator that only backs a page with physical memory the first time it's touched, and a preemptive scheduler that runs everything else in ring 3.

  5. 01Bootloader

    A short real-mode assembly stub enables the A20 line, switches from VGA to a VBE framebuffer, sets up a GDT, and jumps into protected mode. From there, a small C++ stage 2 reads the kernel off the disk and parses its ELF headers before jumping into it.

Memory & Processes

Ring 3, paging, and a scheduler that doesn't cheat

The kernel sets up its own GDT and page tables, then drops every process into ring 3 while it stays in ring 0. Memory is allocated lazily — a page only gets a physical frame the first time a process actually touches it — and pages can be shared read-only or copy-on-write. A preemptive scheduler keeps everything running concurrently on top of it.

Filesystem

A real FAT32 filesystem behind a VFS

USB is BrebOS's primary storage path today: a from-scratch driver (xHCI, Bulk-Only Transport, and the SCSI commands underneath) reads and writes a real USB drive, with an ATA driver kept around as a fallback. A FAT32 implementation reads and writes files on top of whichever one is attached, and a virtual filesystem layer abstracts it all away — so the rest of the kernel, and every syscall like open, read, or stat, doesn't need to know which filesystem or drive is actually backing a path.

VFSopen, read, stat — any filesystem
FAT32The only filesystem today
USB driverxHCI + BOT, primary
ATA driverFallback
Networking

From a raw NIC to an HTTP GET

An E1000 Ethernet driver sits at the bottom of a from-scratch network stack: Ethernet, ARP, IPv4, UDP, ICMP ping replies, DHCP, a still-weak TCP, and enough HTTP on top to make wget actually fetch something. The VM reaches the outside world through NAT, with a local DHCP server handing it an address on boot.

DHCPAuto-config
HTTP GETwget's target
UDPDatagrams
TCPStill thin
IPv4 / ARPRouting + ICMP
E1000 NICEthernet
Toolchain & Userland

A C++ compiler that targets BrebOS

i686-brebos-gcc is a hosted cross-compiler built from scratch to know about BrebOS, mlibc, and libstdc++ internals. Programs are loaded from ELF files, dynamically linked with lazy symbol resolution, and given an ABI-conforming stack — which means ordinary C++, including the STL, RTTI, and exceptions, just works. Adding a new program is one script call away; the build system wires it into /bin automatically.

toolchain
$ i686-brebos-g++ --version
i686-brebos-g++ (GCC) 15.1.0
$ ls toolchain/usr/bin
i686-brebos-addr2linei686-brebos-ari686-brebos-asi686-brebos-c++i686-brebos-c++filti686-brebos-cppi686-brebos-elfediti686-brebos-g++i686-brebos-gcci686-brebos-gcc-15.1.0i686-brebos-gcc-ari686-brebos-gcc-nmi686-brebos-gcc-ranlibi686-brebos-gcovi686-brebos-gcov-dumpi686-brebos-gcov-tooli686-brebos-gprofi686-brebos-ldi686-brebos-ld.bfdi686-brebos-lto-dumpi686-brebos-nmi686-brebos-objcopyi686-brebos-objdumpi686-brebos-ranlibi686-brebos-readelfi686-brebos-sizei686-brebos-stringsi686-brebos-strip
Shell

42sh: a real shell, not a toy prompt

42sh started as a school group project and was ported to run as BrebOS's default shell. It understands a real subset of Linux shell syntax — if/while/for, functions, pipelines, redirections, subshells, command substitution, and variables — everything short of interactive mode. /bin also runs real BusyBox — cat, ls, cut, dirname, factor, printf, wc, yes — cross-compiled with BrebOS's own toolchain and running unmodified, proof the userland is solid enough to host software it didn't write itself.

42sh
$ 42sh --features
  • if / while / for
  • functions
  • pipelinesa | b
  • redirections> >> < 2>
  • subshells( ... )
  • command substitution$( ... )
  • variables$VAR, export
  • interactive mode
+ real BusyBox: cat, ls, cut, dirname, factor, printf, wc, yes
Tooling

A profiler built entirely in-house

GCC's -finstrument-functions hooks every function's entry and exit; a hand-written profiler timestamps each one with rdtsc and accumulates cycle counts per function, dumping the result to /prof.txt. A host-side script then resolves every address back to a function name through the kernel's symbol table and ranks them by share of total cycles — a home-grown gprof, built to find out what the kernel actually spends its time on.

/prof.txt
$ cat /prof.txt | sort -k3 -nr | head -5
FUNCTIONCALLSCYCLESSHAREFat32::readCluster18422842,15031.4%Scheduler::schedule9007356,88013.3%VFS::resolvePath14200301,22511.2%PageFaultHandler::handle5210274,61010.2%Xhci::submitTransfer3110198,0507.4%
Example output — not a real captured run
See It Boot

Booting BrebOS

A recording of BrebOS booting, from GRUB to a working shell — in QEMU, or for real: BrebOS now boots end to end on physical hardware, off a USB stick.

What's Next

Networking and concurrency are next

BrebOS now boots end to end on real hardware — GRUB, kernel, FAT32 over USB, and a working shell — thanks to a from-scratch xHCI and USB mass-storage driver. What's left leans more toward software than hardware.

Built with
  • C++
  • x86 Assembly
  • NASM
  • Custom GCC toolchain
  • mlibc
  • libstdc++-v3
  • xHCI / USB
  • BusyBox
  • GRUB
  • QEMU
Source code