Skip to content

A vibe-coded toy operating system - x86-64, co-op multitasking, no memory protection, written in Rust

Notifications You must be signed in to change notification settings

schani/ralph-os

Repository files navigation

Ralph OS

A simple x86_64 operating system written in Rust.

Design Decisions

No External Dependencies

Ralph OS is implemented entirely from scratch with no external crates. This includes:

  • Custom bootloader (16-bit → 32-bit → 64-bit mode transitions)
  • Custom serial driver (direct UART 16550 register access)
  • Custom memory allocator
  • All other OS components

Only Rust's core library is used. The alloc crate is enabled once we have a custom allocator.

Architecture

  • Target: x86_64 only
  • Single core: No SMP support
  • Cooperative multitasking: Tasks yield control voluntarily via yield_now()

Memory Model

  • Flat address space: No virtual memory, all tasks share the same linear address space
  • Linked list allocator: Supports allocation and freeing (no paging)
  • Identity mapped: Physical addresses = virtual addresses

Application Model

  • ELF executables can be embedded and spawned as tasks
  • BASIC programs are embedded as faux-files (bas/*.bas) and loaded via LOAD "name"

I/O

  • Serial output only: COM1 (0x3F8) via UART 16550
  • Optional graphics: VGA mode 13h can be enabled (see make run-vga*)

Networking

  • NE2000 ISA NIC driver (IRQ 10, I/O base 0x300)
  • TCP/IP stack: Ethernet, ARP, IPv4, ICMP, TCP - all from scratch
  • Non-blocking sockets: Integrates with the cooperative scheduler
  • Telnet server: Per-connection BASIC REPL on TCP port 23

Bootloader

  • Custom two-stage bootloader written in assembly
  • Stage 1: Boot sector (512 bytes), loads stage 2
  • Stage 2: Sets up protected mode, long mode, page tables, loads kernel
  • Identity-mapped page tables (physical = virtual addresses)

Quick Start

# One-time setup (installs Rust nightly and required components)
make setup

# Recommended: VGA + mouse + networking + port forwards
make run-vga-mouse-net

Building

Prerequisites

  1. Rust nightly toolchain (with rust-src and llvm-tools-preview)
  2. NASM assembler
  3. QEMU for x86_64 emulation

Install everything with:

# Install system packages (Ubuntu/Debian)
sudo apt install qemu-system-x86 nasm

# Install Rust tools (run once)
make setup

Make Targets

Command Description
make all Build bootable image (default)
make build Build bootable image
make bootloader Build bootloader only
make kernel Build kernel only
make programs Build all user programs
make image Create bootable disk image
make run Run (serial, no VGA)
make run-net Run with NE2000 + port forwards
make run-net-tap Run with TAP networking (ping support)
make run-vga Run with VGA visualization
make run-vga-mouse Run with VGA + mouse
make run-vga-mouse-net Run with VGA+mouse+network
make test-vga Smoke-test VGA via screenshot
make debug Run with QEMU interrupt logging
make gdb Run with GDB server (port 1234)
make clean Remove build artifacts
make setup Install required Rust tools (run once)
make help Show Makefile help

Manual Build

# Build bootable image
make image

# Run in QEMU
qemu-system-x86_64 \
  -drive format=raw,file=target/ralph_os.img \
  -serial stdio \
  -display none \
  -no-reboot

Debugging with GDB

# Terminal 1: Start QEMU with GDB server
make gdb

# Terminal 2: Connect with GDB
gdb -ex "target remote :1234"

Networking

Ralph OS includes a TCP/IP network stack with:

  • NE2000 NIC driver
  • Ethernet, ARP, IPv4, ICMP, TCP protocols
  • Non-blocking socket API for user programs

Running with Network

# Run with QEMU user-mode networking (no ping from host).
# Also forwards:
# - host tcp/2323 -> guest tcp/23 (telnet)
# - host tcp/8080 -> guest tcp/8080 (HTTP, if you run it)
make run-net

Telnet BASIC REPL

Each telnet connection spawns its own BASIC REPL task.

telnet localhost 2323

HTTP (BASIC)

The repo includes a BASIC program that runs an HTTP server (bas/todo.bas). It is not auto-started; load it from the REPL:

> LOAD "todo"
> RUN

With make run-net / make run-vga-mouse-net, the host forwards localhost:8080 to the guest, so you can hit it from the host:

curl http://localhost:8080/

Network configuration (QEMU user networking defaults):

  • IP: 10.0.2.15
  • Netmask: 255.255.255.0
  • Gateway: 10.0.2.2

Pinging Ralph OS

QEMU's user-mode networking doesn't forward inbound ICMP. To ping the VM, use TAP networking:

# 1. Create TAP interface (one-time setup, requires root)
sudo ip tuntap add dev tap0 mode tap user $USER
sudo ip addr add 10.0.2.1/24 dev tap0
sudo ip link set tap0 up

# 2. Run Ralph OS with TAP networking
make run-net-tap

# 3. In another terminal, ping the VM
ping 10.0.2.15

You should see output like:

[icmp] Echo request from 10.0.2.1 seq=1
[icmp] Sent echo reply to 10.0.2.1 seq=1

To clean up the TAP interface:

sudo ip link set tap0 down
sudo ip tuntap del dev tap0 mode tap

Project Structure

ralph_os/
├── bootloader/
│   ├── stage1.asm          # Boot sector (512 bytes, 16-bit)
│   └── stage2.asm          # Mode transitions (16→32→64-bit)
├── bas/                    # Embedded BASIC programs (*.bas)
├── src/
│   ├── main.rs             # Kernel entry point
│   ├── serial.rs           # Custom UART 16550 driver
│   ├── allocator.rs        # Linked list heap allocator
│   ├── scheduler.rs        # Cooperative task scheduler
│   ├── api.rs              # Kernel API for programs
│   ├── telnet.rs           # Telnet server spawning BASIC sessions
│   ├── basic/              # BASIC interpreter
│   └── net/                # TCP/IP network stack
│       ├── ne2000.rs       # NE2000 NIC driver
│       ├── tcp.rs          # TCP state machine
│       └── ...             # Ethernet, ARP, IPv4, ICMP
├── programs/               # User programs (compiled to ELF)
├── Cargo.toml              # Project manifest (no dependencies!)
├── Makefile                # Build commands
├── kernel.ld               # Kernel linker script
├── x86_64-ralph_os.json    # Custom target specification
├── .cargo/config.toml      # Build configuration
├── README.md               # This file
├── ARCHITECTURE.md         # Technical architecture documentation
└── run.sh                  # Build and run script

See ARCHITECTURE.md for detailed technical documentation.

About

A vibe-coded toy operating system - x86-64, co-op multitasking, no memory protection, written in Rust

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •