Note: There are known issues with version specification throughout the codebase. Version information may not be fully accurate across all files.
A bare-metal x86 operating system kernel written entirely in C and assembly, booting via GRUB Multiboot. Designed as an educational platform for learning OS fundamentals with a working shell, filesystem abstraction, and interrupt handling.
vm_dos provides a minimal but functional kernel environment including:
- Boot: GRUB-based Multiboot protocol entry point
- CPU State: GDT (Global Descriptor Table) and IDT (Interrupt Descriptor Table) setup
- Interrupts: ISR/IRQ handlers with PIC remapping for hardware interrupts
- Timing: PIT (Programmable Interval Timer) for system ticks and sleep functionality
- Memory: PMM (Physical Memory Manager) with bitmap allocator and identity paging
- I/O: VGA text console with color support, keyboard driver with line-buffering
- Filesystem: Minimal VFS layer with ramfs backend for in-kernel file storage
- Userland: Kernel-embedded init system and interactive shell with command parsing
- UI: Themed console layout with toast notifications and progress animations
- i686-elf-gcc — 32-bit ELF GCC cross-compiler
- i686-elf-ld — 32-bit ELF linker
- i686-elf-as — 32-bit assembler (GNU as)
- grub-mkrescue — ISO generation tool (or xorriso as fallback)
- xorriso — ISO9660 creation utility
- qemu-system-i386 — x86 system emulator
# Install cross-compiler and tools
sudo apt-get install gcc-i686-linux-gnu binutils-i386-linux-gnu
sudo apt-get install grub-pc-bin xorriso
sudo apt-get install qemu-system-x86# Full clean rebuild and boot
make run
# Build kernel only
make
# Clean build artifacts
make cleanThe make run target rebuilds from scratch and automatically launches the kernel in QEMU.
vm_dos/
├── kernel/ # Kernel core
│ ├── arch/x86/ # CPU-specific (GDT, IDT, ISR, paging, PMM)
│ ├── lib/ # Utilities (string.h, etc.)
│ ├── shell/ # Interactive shell
│ ├── ui/ # Console UI (theme, layout, animations)
│ └── kernel.c # Main kernel entry (kmain)
├── fs/ # Filesystem layer (VFS, ramfs)
├── user/ # Userland (init process)
├── boot/ # GRUB config
├── iso/ # ISO build staging
├── build/ # Compiled objects and final ELF
├── Makefile
├── linker.ld # Linker script (memory layout)
└── multiboot.s # Multiboot header stub
- GRUB loads
multiboot.s(Multiboot protocol header) - Bootloader jumps to
kernel/arch/x86/boot.S(stack setup, enable paging) - Control passes to
kmain()inkernel.c - System initialization: GDT → IDT → ISRs → PIC → PIT → PMM → Paging
- Userland init starts; shell loop begins
- 0x00100000 — Kernel load address (1 MB, typical Multiboot location)
- Identity mapping — Virtual = Physical (simplified paging)
- Stack — Grows downward from high memory
- Heap — Managed by PMM (bitmap-based)
- ISR Table — 32 CPU exceptions (faults, traps, aborts)
- IRQ Routing — 8 legacy IRQs remapped via PIC
- Keyboard — IRQ1 handler reads scan codes; line-buffering with backspace support
- PIT Timer — IRQ0 fires at 100 Hz; used for
pit_sleep()and animations
- VGA Mode — 80×25 text color (16-color palette)
- Console API —
con_write(),con_write_at(),con_putc_at(),con_clear(),con_box() - Theme — Single default color scheme (foreground, background, accent, status indicators)
- Animations — Toast notifications, progress bars, startup animation
- Layout — Chrome frame, command input area, status line
help— List available commandsclear— Clear screen and redraw UIecho <text>...— Print text to consolepanel— Redraw UI chromeprogress— Animated progress bar demo (40-char width, 4-second duration)ls [path]— List files in filesystem (default:/)cat <path>— Display file contentstoast <message>— Show temporary notificationstatus— Show system status and uptime
When you start vm_dos, you'll see a multi-panel interface:
- Top bar — Shows system name
- Left panel — File browser showing available files and directories
- Center panel — Interactive shell for entering commands
- Right panel — System information display
- Bottom bar — Help text and status messages
Press ENTER with no command to toggle between normal and fullscreen shell mode, which provides more space for command output.
Commands follow standard format:
> command [argument] [argument] ...
Arguments are separated by spaces. Example:
> echo Hello World
> cat /bin/init.txt
> ls /
Usage: help
Description: Display list of all available commands with brief descriptions.
Example:
> help
Available commands:
help - Show this message
clear - Clear screen
echo - Print text
ls - List files
cat - Show file contents
toast - Show notification
status - Show system status
Usage: clear
Description: Clears the screen and redraws the UI chrome (panels and borders). Useful for resetting the display.
Example:
> clear
Usage: echo <text> [text] ...
Description: Prints text to the shell output. Multiple arguments are space-separated. Useful for displaying messages and testing output.
Example:
> echo Hello World
Hello World
> echo Welcome to vm_dos
Welcome to vm_dos
Usage: status
Description: Display system status information including kernel version, shell status, and system uptime in minutes and seconds.
Example:
> status
-- System Status --
Status: Running OK
Kernel: v1.0.1
Shell: Active
Usage: ls [path]
Description: List files in the filesystem at the specified path. If no path is given, lists the root directory /. The filesystem is read-only and contains only embedded files.
Available paths:
/— Root directory/bin/— Binary/executable directory/bin/init.txt— Main initialization file
Example:
> ls
/bin/init.txt
> ls /bin
init.txt
> ls /
bin/
Usage: cat <path>
Description: Display the contents of a file. Requires an argument specifying the file path. Useful for viewing file contents and system information.
Example:
> cat /bin/init.txt
[displays file contents]
Usage: toast [message]
Description: Show a temporary notification message at the bottom of the screen that automatically disappears after ~3 seconds. If no message is provided, shows default "Toast!" message.
Example:
> toast Hello there
[notification appears briefly at bottom of screen]
> toast System check complete
[custom notification appears]
Usage: panel
Description: Redraw the UI panel/chrome. Useful if the display becomes corrupted or needs refreshing.
Example:
> panel
System panel refreshed.
Usage: progress
Description: Display an animated progress bar demonstration (40 characters wide, approximately 4 seconds). Shows how animations work in the kernel.
Example:
> progress
[displays animated progress bar: ########################################]
Done
- ENTER (empty) — Toggle between normal and fullscreen shell modes
- ESC — Return to menu (from fullscreen mode)
- Backspace — Delete character in input
- ENTER (with text) — Execute the command
> help
Available commands:
help - Show this message
clear - Clear screen
echo - Print text
ls - List files
cat - Show file contents
toast - Show notification
status - Show system status
> status
-- System Status --
Status: Running OK
Kernel: v1.0.1
Shell: Active
> ls
/bin/init.txt
> cat /bin/init.txt
[file contents displayed]
> echo Command execution working!
Command execution working!
> toast System check passed
[notification shown]
- Use
echofor testing — Verify the shell is responsive by echoing text - Check
statusfor uptime — Monitor how long the system has been running - List files to explore filesystem — Use
lsto see what files are available - Fullscreen mode for large output — Press ENTER to switch modes for better readability
- Read init file — Use
cat /bin/init.txtto see embedded system information
- ramfs Backend — All files stored in kernel memory as a simple array
- Paths — Unix-style paths (
/,/bin/init.txt) - Init File — Embedded text file at
/bin/init.txt(can be edited infs/initrd.c) - Limitations — Read-only, no directories, flat namespace
- Bitmap Allocator — One bit per 4 KB page frame
- API —
pmm_alloc(),pmm_free(),pmm_init() - Scope — Manages kernel heap; not for user processes (yet)
The Makefile compiles each .c file to object files, assembles .S (uppercase) assembly, and links all objects with linker.ld. Key flags:
-m32— Generate 32-bit x86 code-ffreestanding— No libc, no runtime support-nostdlib -nostdinc— Exclude standard library headers-fno-pic -fno-pie— No position-independent code (kernel must load at fixed address)
- Write command function in
kernel/shell/commands.c:static int cmd_mycommand(int argc, const char **argv) { con_write_at(25, 10, "Hello from my command!"); return 0; }
- Add entry to
COMMANDS[]array:{"mycommand", "My help text", cmd_mycommand}, - Rebuild with
make run
- Edit colors in
kernel/ui/theme.c(default theme structure) - Redraw chrome in
kernel/ui/layout.c(ui_draw_chrome()) - Change startup message and banner in
kernel/kernel.c
- Edit
fs/initrd.cto add more entries to the ramfs - Update path references in shell or userland code
- No dynamic file creation yet (filesystem is static)
- Single theme — No runtime theming; compile-time only
- No real userspace — Init and shell run in kernel mode (no privilege separation)
- Read-only filesystem — ramfs is static; no write/delete operations
- Limited keyboard — ASCII printables only; no modifier keys or function keys
- Basic PMM — Bitmap-based; no buddy allocator or sophisticated strategies
- No virtual memory — Identity paging only; no demand paging or swapping
- Proper userspace with ring 3 execution
- ELF loader for dynamic programs
- Real process management (scheduling, context switching)
- Writable filesystem (tmpfs, ext2)
- System call interface (gate, argument passing, return values)
- PCI enumeration and driver framework
- ATA/AHCI disk controller support
- Networking stack (if disk support is added)
- "unrecognized command-line option '--m32'" — Use
-m32(single dash), not--m32 - "missing .note.GNU-stack" — Assembly warning; can be ignored. Add
.section .note.GNU-stack, "", %progbitsto.Sfiles to suppress.
- QEMU window shows nothing — Check terminal output; kernel may have panicked. Look for early boot messages.
- Shell doesn't respond to input — Keyboard driver may not be initialized. Verify IRQ1 is unmasked after PIC remap.
- File not found — ramfs paths must match entries in
fs/initrd.c. Uselsto debug.
- Use WSL2 with Ubuntu; install cross-compiler in WSL
- Run
make runfrom WSL terminal - QEMU can display to X11 forwarding or use
-display noneand-serial stdiofor serial output only
- No ANSI Escape Sequences — VGA text mode doesn't interpret escape codes. Use console API functions instead.
- Bare Metal — No libc means no
printf(),malloc(), standard I/O. Everything is custom. - Educational Focus — Code prioritizes clarity over performance; not suitable for production.
- x86-32 Only — Currently targets i686 (Pentium+). x86-64 support would require significant changes.
Public domain / MIT — your choice. Use freely for learning, experimentation, and iteration.