Releases: Jovinull/StinkOS
v0.7.0: COW fork
paging_copy_user_pgdir no longer eagerly duplicates every user frame.
At fork time, parent and child share frames; writable pages are tagged
PG_COW (PTE software bit 9) and have their RW bit cleared on BOTH
sides. The first writer takes a #PF which a new paging_handle_cow_fault
resolves by either restoring RW (last owner) or allocating + copying
into a fresh frame (the writer's PTE then points at the private copy
while the original sticks with the other owner).
Read-only pages (.text / .rodata under v0.5 W^X) stay shared without
PG_COW -- writes to those remain real W^X violations and the trap path
kills the offender as before.
Cuts fork cost from "memcpy every present user frame" to "flip RW +
ref_inc". Typical apps that fork then exec touch only a handful of
pages before the exec replaces everything, so most copies that the
eager path performs never have to happen at all.
PMM gains a per-frame u8 refcount (pmm_ref_inc, pmm_free now ref-aware,
pmm_ref for diagnostics). Single-CPU only -- when SMP lands, refcount
- COW need atomic ops + per-CPU lock.
4 atomic commits: PMM refcount, COW infra, smoke-cow test, CHANGELOG.
v0.6.0: ACPI static-table parsing
Section 7 ACPI lands: kernel locates the RSDP via the IA-PC scan
(EBDA + BIOS area), walks the RSDT (ACPI 1.0) or XSDT (2.0+), and
parses the two tables we actually need today: FADT for soft-off
shutdown and MADT for CPU + IOAPIC topology.
sys_shutdown now tries real ACPI S5 first (FADT-described PM1a_CNT_BLK
port write) and only falls back to the legacy QEMU / Bochs / VirtualBox
port-magic paths when ACPI is absent. MADT reports CPU count + LAPIC
base + IOAPIC base on the boot serial line, ready for the future SMP
bring-up.
No AML interpreter: SLP_TYPa is hardcoded to 5 (the value used by
essentially every PC firmware including QEMU). See TODO.md "AML
interpreter -- FUTURE" for the honest impact assessment on laptop
hardware and the path forward if we ever need it.
4 atomic commits plus a follow-up smoke-acpi test target on master.
v0.5.0: PAE + W^X
Section 7 of the roadmap. Paging upgrades from 32-bit 2-level (4 MiB
PSE) to PAE 3-level (PDPT -> PD -> PT, 8-byte entries, NX at bit 63),
and W^X lands across kernel image + every user process.
Kernel image refuses execution from its own .data / .bss and refuses
writes to .text / .rodata. Userland apps are linked with three program
headers so each segment's PTE permissions match the ELF p_flags:
.text R-X, .rodata R-NX, .data + .bss RW-NX. A new wxattack ELF proves
the gate fires: it stamps a one-byte shellcode into a global and calls
it via a function pointer; the CPU page-faults at the first instruction
fetch and the kernel kills the process.
8 atomic commits collapsing a 10-step plan. Side fixes:
paging_copy_user_pgdir now allocates its own PD0 (sys_fork was
dereferencing zero before); apps/game.s writable globals moved from
.text into .section .data (W^X turned the in-place writes into #PF
until the move).
v0.4.0-rc2
StinkOS v0.4.0-rc2 -- see CHANGELOG / commits for details.
v0.4-rc1
StinkOS v0.4-rc1 -- see CHANGELOG / commits for details.
StinkOS v0.3.0 — userland, networking, audio, package manager & Doom
StinkOS v0.3.0 — a real 32-bit x86 operating system written from scratch in C and assembly. No libc, no prebuilt kernel, no external runtime dependencies. Boots on QEMU and on real PC hardware (BIOS/legacy boot).
This is the first tagged release, and it's a big one: v0.3 turns StinkOS from a kernel-with-demos into a small but genuine platform — a graphical userland that loads independent ELF apps from its own filesystem, a from-scratch TCP/IP network stack, DMA-driven audio, an in-OS package manager, and a working Doom port riding on top of all of it.
What it is
A real OS, same shape as the big ones — just smaller in every direction. On boot it loads itself from disk via the BIOS, enables A20, builds a GDT, switches the CPU into 32-bit protected mode, sets a VBE linear framebuffer (1024×768×32), wires up interrupts and paging, installs a TSS, and drops into a graphical start menu. From there it loads named ELF binaries off its own filesystem and runs them in Ring 3 with isolated address spaces — a misbehaving app faults and returns to the menu instead of taking down the system. Apps talk to the kernel only through an int 0x80 syscall ABI.
What this release offers
- Userland & graphical shell — an on-screen terminal with ~25 commands (
ls,cat,write,rm,cp,mv,touch,grep,head,tail,wc,hexdump,history,netinfo/ifconfig,ping,run, …) and arrow-key command history; a full-screen text editor; Snake and Pong. - Filesystem (StinkFS + VFS) — flat named files persisted to disk, a file-descriptor layer (open/read/write/seek/close), and an ELF loader that streams app segments straight off disk. Apps live as named files and show up in the menu automatically.
- Networking from scratch — Intel e1000 NIC driver (PCI probe, RX/TX descriptor rings), Ethernet, ARP, IPv4, ICMP, UDP, a TCP state machine with ACK accounting, a DHCP client, and a DNS resolver. Surfaced through the shell's
netinfoandping. - Storage — ATA driver across all four drive slots with Bus Master DMA (PIIX BMIDE), MBR partition read/write, and disk info/copy syscalls. An installer app can clone the boot media onto a target disk.
- Audio — Sound Blaster 16 driver (DSP probe, IRQ 5, ISA 8237 DMA, 22050 Hz auto-init output) plus an 8-channel kernel software mixer, exposed to apps via audio syscalls. PC speaker driver too.
- Package manager (
stink-pkg) — an in-OS package manager with its own HTTP client and a.stinkpkgformat; downloads are verified by SHA-256 against the repo index before install. - Input & misc — PS/2 keyboard (arrows, Caps Lock, Ctrl, Home/End/PgUp/PgDn) and PS/2 mouse with cursor and point-and-click; CMOS RTC with a live clock in the menu.
- Boot diagnostics — a BIOS-style POST screen reporting each subsystem's status as it comes up.
- A ~44-call syscall ABI wrapped as static inlines in
lib/libstink.h, plus a freestanding C library (malloc/free over a growable heap, aFILEstdio layer, printf family, string/ctype/mem helpers,setjmp, SHA-256). - Doom — all of Doom 1 (36 maps), Doom 2 (32 maps), and FreeDM run as Ring 3 apps. Disabled in this image by default (see below).
Requirements
qemu-system-i386to run in a VM, or a BIOS/legacy-boot PC to run on metal.- To build from source: the
i386-elfcross-toolchain andpython3(see the repo README).
Quick start — run the prebuilt image
Download stinkos-v0.3.0.img.gz, then:
gunzip stinkos-v0.3.0.img.gz
qemu-system-i386 -drive format=raw,file=stinkos-v0.3.0.img \
-netdev user,id=net0 -device e1000,netdev=net0 \
-audiodev none,id=snd0 -device sb16,audiodev=snd0The -device e1000 / -device sb16 flags light up the network and audio drivers; drop them for a bare boot. The disk image is ~98 MiB raw because it carries StinkFS's full data region (mostly empty here — it compresses to ~0.6 MiB).
Run on real hardware
Write the raw image to a USB stick or disk and boot it on a BIOS/legacy machine (not UEFI-only):
sudo dd if=stinkos-v0.3.0.img of=/dev/sdX bs=4M conv=fsync # ⚠ /dev/sdX is ERASED — pick the right deviceEnabling Doom
The Doom menu entries (DOOM1 / DOOM2 / FREEDM) are greyed out in this image because no WADs are bundled — game content is not part of the source and isn't redistributed here. To play, build from source with the free Freedoom WADs:
git clone https://github.com/Jovinull/StinkOS && cd StinkOS
bash tools/fetch-wads.sh # downloads freedoom + freedm (~33 MB) into wads/
make runHave a commercial doom.wad/doom2.wad? Drop it in wads/ and override: make FREEDOOM1_WAD=path/to/doom.wad.
Build from source
bash tools/build-cross-toolchain.sh # one-time: builds i386-elf binutils+gcc (~30–60 min)
source ~/.bashrc
make # produces os.bin
make test-headless # boots in qemu and asserts subsystem bring-up
make run # interactiveVerify your download
sha256sum -c SHA256SUMSSHA256SUMS lists checksums for both the compressed .img.gz and the decompressed .img.
Assets
| File | What it is |
|---|---|
stinkos-v0.3.0.img.gz |
Bootable raw disk image (gzip). gunzip it, then boot in QEMU or dd to a disk. |
SHA256SUMS |
SHA-256 checksums for the image (compressed and decompressed). |
| Source code (zip / tar.gz) | Full source at tag v0.3.0 (auto-attached by GitHub). |
Known limitations
- Single-process: one Ring 3 app runs at a time (returns to the menu on exit/fault). Preemptive multitasking is next.
- Doom runs without music/sound effects and without mouse-aim wired to the engine yet (the SB16 driver and mouse-delta syscall both exist; the glue doesn't).
- BIOS/legacy boot only — no UEFI.
License
GPLv3. The vendored Doom engine under apps/doom/ is also GPL and is attributed in-tree. Everything else is original.

