Architecture - cupidthecat/cupid-os GitHub Wiki

Architecture

cupid-os is a monolithic, single-address-space, ring-0 operating system for 32-bit x86. Every component - kernel, drivers, shell, applications - runs in the same flat memory space with full hardware access.


Boot Sequence

BIOS loads boot.asm at 0x7C00 (real mode, 16-bit)
    β”‚
    β”œβ”€β”€ Set up stack at 0x7C00
    β”œβ”€β”€ Load kernel from disk (sectors 1+) to 0x10000
    β”œβ”€β”€ Set 640Γ—480Γ—32bpp via Bochs VBE I/O ports (0x01CE/0x01CF)
    β”œβ”€β”€ Read VBE LFB address from PCI BAR0 β†’ store at 0x0500
    β”œβ”€β”€ Set up GDT (flat model: code + data segments)
    β”œβ”€β”€ Switch to protected mode (CR0 bit 0)
    └── Far jump to kernel entry at 0x10000
            β”‚
            β”œβ”€β”€ idt_init()          - Interrupt Descriptor Table
            β”œβ”€β”€ pic_init()          - PIC remapping (IRQ0β†’32, IRQ8β†’40)
            β”œβ”€β”€ irq_init()          - IRQ handler registration
            β”œβ”€β”€ pmm_init()          - Physical memory manager
            β”œβ”€β”€ paging_init()       - Identity-mapped 4KB pages (32MB)
            β”‚                         + maps VBE LFB region from 0x0500
            β”œβ”€β”€ heap_init()         - Kernel heap (2MB) with canaries
            β”œβ”€β”€ keyboard_init()     - PS/2 keyboard (IRQ1)
            β”œβ”€β”€ pit_init()          - PIT at 100Hz (IRQ0)
            β”œβ”€β”€ serial_init()       - COM1 at 115200 baud
            β”œβ”€β”€ rtc_init()          - CMOS Real-Time Clock
            β”œβ”€β”€ fat16_init()        - FAT16 filesystem + block cache
            β”œβ”€β”€ fs_init()           - In-memory filesystem
            β”œβ”€β”€ vfs_init()          - Virtual File System
            β”‚   β”œβ”€β”€ Register ramfs, devfs, fat16 filesystem types
            β”‚   β”œβ”€β”€ Mount ramfs at /
            β”‚   β”œβ”€β”€ Create /bin, /tmp, /home directories
            β”‚   β”œβ”€β”€ Mount devfs at /dev (null, zero, random, serial)
            β”‚   β”œβ”€β”€ Mount fat16 at /home (ATA disk)
            β”‚   └── Pre-populate /LICENSE.txt, /MOTD.txt
            β”œβ”€β”€ process_init()      - Process table, idle process (PID 1)
            β”œβ”€β”€ Register desktop as PID 2
            β”œβ”€β”€ vga_init_vbe()      - Init 640Γ—480 32bpp framebuffer
            β”œβ”€β”€ mouse_init()        - PS/2 mouse (IRQ12)
            └── desktop_run()       - Main event loop

Memory Layout

0x00000000 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ Interrupt Vector Table   β”‚ (not used - we use IDT)
0x00000500 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ VBE LFB address          β”‚ ← Written by bootloader
0x00001000 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ Kernel Code + Data       β”‚ ← Loaded by bootloader
           β”‚ (.text, .data, .bss)     β”‚ ← starts at 0x10000
           β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ Boot Stack               β”‚ ← 0x7C00 (real mode)
0x00110000 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ Stack Guard Region       β”‚ ← 512KB kernel stack
0x00190000 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ Kernel Heap              β”‚ ← kmalloc/kfree, 2MB
           β”‚ (canary-protected)       β”‚ ← includes VBE back buffer
           β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ Process Stacks           β”‚ ← kmalloc'd, 4KB+ each
           β”‚ (canary at bottom)       β”‚
0x000A0000 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ VGA Text Memory          β”‚ ← Text mode (legacy)
0x00100000 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ Extended Memory          β”‚ ← PMM bitmap manages this
           β”‚ (pages allocated here)   β”‚
0x02000000 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
           β”‚ End of managed memory    β”‚ (32MB total)
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           Β·
           Β· (unmapped gap)
           Β·
0xFD000000 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ VBE Linear Framebuffer   β”‚ ← 640Γ—480Γ—4 = 1.2MB
           β”‚ (identity-mapped by      β”‚   PCI BAR0, QEMU default
           β”‚  paging_init)            β”‚
0xFD140000 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Component Architecture

Kernel Core

Component Files Purpose
Kernel entry kernel.c/h VGA, init sequence, main print functions
IDT idt.c/h Interrupt descriptor table setup
ISR/IRQ isr.asm, irq.c/h Interrupt/exception dispatching
PIC pic.c/h Programmable interrupt controller
Memory memory.c/h, paging.c PMM, heap, paging, canaries, leak detection
VFS vfs.c/h Virtual filesystem, mount table, path resolution
Panic panic.c/h, assert.h Crash handler, assertions
Strings string.c/h strlen, strcmp, memcpy, memset
Math math.c/h 64-bit division, itoa, hex printing

Drivers

Driver Files IRQ Purpose
Keyboard keyboard.c/h IRQ1 PS/2 input with modifiers
Mouse mouse.c/h IRQ12 PS/2 mouse with cursor
Timer timer.c/h, pit.c/h IRQ0 100Hz PIT, uptime, sleep
VGA vga.c/h - VBE 640Γ—480 32bpp, double buffering
ATA ata.c/h - PIO disk read/write
Serial serial.c/h - COM1 logging
Speaker speaker.c/h - PC speaker tones
RTC rtc.c/h - CMOS real-time clock

Subsystems

Subsystem Files Purpose
Shell shell.c/h 38-command interactive shell with CWD support
CupidScript cupidscript*.c/h Bash-like scripting language
Ed Editor ed.c/h Unix ed(1) line editor
VFS vfs.c/h Virtual File System with mount table and path resolution
RamFS ramfs.c/h In-memory filesystem (root, /bin, /tmp)
DevFS devfs.c/h Device filesystem (/dev/null, zero, random, serial)
FAT16 VFS fat16_vfs.c/h FAT16 VFS wrapper for /home
FAT16 fat16.c/h, blockdev.c/h, blockcache.c/h FAT16 driver with block cache
In-Memory FS fs.c/h Legacy read-only system file table
Exec exec.c/h CUPD program loader
Process Mgr process.c/h, context_switch.asm Scheduler, context switching
GUI gui.c/h, desktop.c/h, graphics.c/h, font_8x8.c/h Window manager, desktop
Terminal terminal_app.c/h GUI terminal application
Notepad notepad.c/h Text editor application (VFS file dialog)
Clipboard clipboard.c/h System clipboard
Calendar calendar.c/h Calendar math, time/date formatting, popup state

Interrupt Map

IRQ Vector Handler Purpose
IRQ0 32 timer_callback PIT timer tick (100Hz), scheduler flag
IRQ1 33 keyboard_handler PS/2 keyboard input
IRQ12 44 mouse_handler PS/2 mouse input
- 0 division_error Divide by zero exception
- 6 invalid_opcode Invalid opcode exception
- 13 general_protection GPF
- 14 page_fault Page fault (with CR2 reporting)

Execution Model

cupid-os uses deferred preemptive multitasking:

  1. PIT IRQ0 fires every 10ms β†’ sets need_reschedule flag
  2. Flag is checked at safe voluntary points only:
    • Desktop main loop (before HLT)
    • process_yield() calls
    • Idle process loop
  3. Context switch happens via pure assembly context_switch():
    • Save EBP, EDI, ESI, EBX, EFLAGS on current stack
    • Store ESP into old process PCB
    • Load new process ESP and jump to new EIP

This avoids the complexity and stack corruption risks of switching inside interrupt handlers.


CupidScript Execution Pipeline

.cup file on disk
      β”‚
      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Lexer     │───▢│    Parser    │───▢│  Interpreter β”‚
β”‚ (tokenize)   β”‚     β”‚ (build AST)  β”‚     β”‚ (execute AST)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                                                  β”‚
                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                           β–Ό                      β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Runtime    β”‚     β”‚    Shell     β”‚
                    β”‚ (variables,  β”‚     β”‚ (execute_    β”‚
                    β”‚  functions)  β”‚     β”‚  command())  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

See Also