StinkOS

A 32-bit x86 operating system written from scratch. Boots from a custom ELF-aware bootloader, schedules processes, talks TCP/IP, ships a package manager, and runs Doom.

i386 freestanding MBR boot (no GRUB) multiboot-compatible kernel QEMU + real PC MIT (first-party)
Freedoom1 running as a userland app on StinkOS, picking up a shotgun in Phase 1 Map01

Freedoom1 running as a userland app -- ring 3, no GRUB, no Multiboot loader. Bootblock -> ELF kernel -> doomgeneric.

~110 KiBstripped kernel
44syscalls
28userland apps
62+host unit tests
239+v0.4 commits
0third-party libs in kernel

What is inside

Boot & kernel

  • ELF-aware bootloader: 16-sector bootblock loads kernel.elf from disk, walks PT_LOAD program headers, jumps to entry.
  • Multiboot-1 header in the kernel ELF so GRUB can boot it too.
  • Kernel linked at 0x100000; userland window at 0x400000.
  • Flat 4 GiB identity-mapped paging, separate user code/heap/stack windows.
  • GDT + IDT + PIT @ 100 Hz, PIC remapped, full IRQ dispatch.

Multitasking

  • Process control block, process table (PROC_MAX = 16).
  • Kernel-stack context switch; round-robin scheduler driven by the PIT IRQ.
  • Anonymous pipes, cooperative signals (SIGINT/SIGTERM), per-process VFS.
  • SYS_GETPID / KILL / WAIT / WAITPID / SETPRIO / SUSPEND / RESUME / PROC_INFO.
  • Mid-syscall preemption (interrupts re-enabled inside syscall_dispatch).

Network stack

  • TCP RFC 793: retransmit + RTO, slow start, cwnd, fast retransmit, OOO reassembly, MSS, window-scale, SACK, keepalive, persist probe, TIME_WAIT reap.
  • IPv4 with martian filter, Teardrop guard, 2-slot fragment reassembly, source-route drop.
  • DHCP (with retry + secondary DNS), DNS cache, ARP cache with TTL eviction.
  • e1000 NIC driver, IRQ-driven RX.
  • BSD-style sockets: bind / listen / accept / connect.

Userland & shell

  • 30+ shell commands: ps kill suspend resume mem netstat dns arp dmesg vol audio keymap alarm shutdown reboot clock hostname.
  • 256-line scrollback, persisted command history (SHELL.HIS).
  • BR ABNT2 + US keymaps, runtime switch.
  • UTF-8 multi-byte collapse in scrollback.

Storage & FS

  • StinkFS: contiguous-file FS on a raw partition, ~100 MiB data region.
  • VFS layer with per-process fd table, open/read/write/seek/close.
  • ATA driver with PIIX bus-master DMA + PIO fallback.
  • Real MBR partition tables on install media.

Audio

  • SB16 driver, ISA DMA on channels 1 (8-bit) and 5 (16-bit stereo).
  • 8-channel software mixer with Q16.16 per-channel resampling.
  • Half-buffer IRQ for low latency, master + per-channel volume.
  • Doom SFX wired to the kernel mixer.

Doom port

  • doomgeneric + Freedoom1 / Freedoom2 / FreeDM ship as three apps.
  • Fullscreen via SYS_BLIT_SCALED (kernel-side nearest-neighbour).
  • Save games via VFS; demos via DOOMARGS.CFG (-record, -playdemo).

Package manager

  • .stinkpkg archive format with optional compression.
  • stink-pkg install / query / upgrade / verify / replay.
  • Recursive dependency resolution.
  • SHA-256-hashed manifests, lockfile (STINKPKG.LCK).

Screenshots

StinkOS boot menu listing 25 userland apps including Doom variants
The boot menu lists every userland app on the disk -- 25 apps in this image, picked by ENTER on the highlighted entry.
Freedoom1 mid-combat with pistol drawn, status bar showing 93% health
Freedoom1 mid-combat. Status bar (health, ammo, armor, weapons grid) is the original Doom HUD running through doomgeneric.
StinkOS shell running help, mem, ps, and netinfo commands back to back
The shell chained through help / mem / ps / netinfo. DHCP bound, gateway and DNS picked up from QEMU's user-mode SLIRP, free-page count exposed via SYS_MEMINFO.
FBDEMO app writing colour bars directly to the linear framebuffer
SYS_MAP_FB in action -- the framebuffer is mapped read-write into the user address space, so each pixel write is one store instruction, zero syscalls.

Get started

01.

Boot the latest ISO

Download from GitHub Releases. The ISO is a raw disk image -- write to a USB stick or run in QEMU:

qemu-system-i386 -drive format=raw,file=stinkos-install.iso \
  -netdev user,id=net0 -device e1000,netdev=net0 \
  -audiodev sdl,id=snd0 -device sb16,audiodev=snd0

02.

Build from source

Linux or WSL. Needs an i386-elf cross-toolchain (the build script grabs it):

git clone https://github.com/Jovinull/StinkOS.git
cd StinkOS
bash tools/build-cross-toolchain.sh   # one-time, ~15 min
make                                  # builds os.bin + kernel.elf
make run                              # boots in QEMU

03.

Run the tests

62 host-side unit tests pin the kernel's decision logic without QEMU:

make unittest          # all 62 host tests
make test-headless     # full QEMU boot + every app
make readelf-kernel    # PT_LOAD inspection

Package repository

This site hosts a sample .stinkpkg repository so a fresh StinkOS install can fetch software out of the box. Point your install at this URL by writing STINKPKG.CONF:

repo_url=https://jovinull.github.io/StinkOS

Then on the running system:

stink-pkg install snake
stink-pkg install pong
stink-pkg upgrade

Browse the live package index →

Documentation

The kernel is documented in tree -- every subsystem has a markdown doc tied to it.

Contributing

The repo accepts PRs. Branch protection on master requires the headless boot test to pass; CI runs the cross-toolchain build and every host-side unit test on every push.

Open issues for any of the items in the changelog backlog -- per-process CR3, sys_fork, AC97/HDA audio, PXE install, rtl8139 / virtio-net, IPv6 -- and the rest of the multi-process and driver surface.

Pick something small to start: there is a list of TODO §X.Y markers across the kernel that are explicitly tagged for new contributors.