mirror of
https://github.com/johndoe6345789/MetalOS.git
synced 2026-04-24 13:45:02 +00:00
Embrace extreme minimalism - cut everything unnecessary
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
79
README.md
79
README.md
@@ -1,8 +1,25 @@
|
||||
# MetalOS
|
||||
|
||||
A minimal operating system built from the ground up to run QT6 applications on AMD64 hardware with Radeon RX 6600 GPU and UEFI boot.
|
||||
**The most minimal OS possible that runs QT6 Hello World.**
|
||||
|
||||
**Not Linux. Not BSD. Not Windows.** Just enough OS to run a QT6 Hello World full-screen application.
|
||||
Not Linux. Not BSD. Not Windows. Just enough code to boot, initialize GPU, and run one app.
|
||||
|
||||
## Extreme Minimalism
|
||||
|
||||
MetalOS is an exercise in **absolute minimalism**:
|
||||
|
||||
- ❌ **No scheduler** - one app = always running
|
||||
- ❌ **No process management** - one process only
|
||||
- ❌ **No file system** - app embedded in boot image
|
||||
- ❌ **No networking** - not needed
|
||||
- ❌ **No shell/command line** - boot directly to app
|
||||
- ❌ **No security** - trust everything
|
||||
- ❌ **No multi-core** - one CPU core
|
||||
- ❌ **No dynamic linking** - static link everything
|
||||
|
||||
**If it doesn't help QT6 Hello World run, it doesn't exist.**
|
||||
|
||||
Target: **< 200 KB OS code** (excluding QT6 itself)
|
||||
|
||||
## Project Status
|
||||
|
||||
@@ -12,7 +29,23 @@ Currently: Project structure, documentation, and skeleton code in place.
|
||||
|
||||
## What is MetalOS?
|
||||
|
||||
MetalOS is a **minimal, purpose-built operating system** with a single goal: demonstrate that you can build a custom OS from scratch to run modern GUI applications (specifically QT6).
|
||||
MetalOS is **the smallest possible operating system** that can boot QT6 Hello World on specific hardware.
|
||||
|
||||
### Philosophy
|
||||
|
||||
Every feature must answer: **"Does this help run QT6 Hello World?"**
|
||||
|
||||
If no → it doesn't exist.
|
||||
|
||||
### Aggressive Minimalism
|
||||
|
||||
- **Bootloader**: < 10 KB (just load kernel and jump)
|
||||
- **Kernel**: < 100 KB (memory, interrupts, drivers)
|
||||
- **GPU Driver**: < 50 KB (minimal display init)
|
||||
- **Input Drivers**: < 20 KB (keyboard + mouse only)
|
||||
- **Total OS**: ~200 KB
|
||||
|
||||
Compare to Linux kernel: ~30 MB. We're **150x smaller** by doing only one thing.
|
||||
|
||||
### Key Features
|
||||
|
||||
@@ -82,10 +115,13 @@ See [docs/BUILD.md](docs/BUILD.md) for instructions on creating a bootable USB d
|
||||
|
||||
## Documentation
|
||||
|
||||
- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** - System design and architecture
|
||||
- **[BUILD.md](docs/BUILD.md)** - Build instructions and dependencies
|
||||
- **[DEVELOPMENT.md](docs/DEVELOPMENT.md)** - Development workflow and guidelines
|
||||
- **[ROADMAP.md](docs/ROADMAP.md)** - Development phases and timeline
|
||||
- **[MINIMALISM.md](docs/MINIMALISM.md)** - ⭐ **START HERE** - Philosophy and what we cut
|
||||
- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** - System design (minimal version)
|
||||
- **[ROADMAP.md](docs/ROADMAP.md)** - Development phases
|
||||
- **[BUILD.md](docs/BUILD.md)** - Build instructions
|
||||
- **[DEVELOPMENT.md](docs/DEVELOPMENT.md)** - Development workflow
|
||||
- **[COMPONENTS.md](docs/COMPONENTS.md)** - Component checklist
|
||||
- **[STATUS.md](docs/STATUS.md)** - Current implementation status
|
||||
|
||||
## Project Structure
|
||||
|
||||
@@ -116,13 +152,13 @@ See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed breakdown.
|
||||
|
||||
## Why?
|
||||
|
||||
**Learning**: Building an OS from scratch is the ultimate systems programming education.
|
||||
**Minimalism**: How small can an OS be and still run GUI apps?
|
||||
|
||||
**Minimal Design**: Modern OSes are complex. This project asks: "What's the absolute minimum needed for a GUI application?"
|
||||
**Learning**: Building an OS from scratch is the ultimate systems programming challenge.
|
||||
|
||||
**Custom Hardware**: Show that you can optimize an OS for specific hardware instead of supporting everything.
|
||||
**Proof of Concept**: Modern frameworks like QT6 can run on tiny custom OSes.
|
||||
|
||||
**QT6 Demo**: Prove that modern application frameworks can run on custom OS implementations.
|
||||
**Fun**: Because we can.
|
||||
|
||||
## Technology Stack
|
||||
|
||||
@@ -142,15 +178,22 @@ See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed breakdown.
|
||||
|
||||
## Contributing
|
||||
|
||||
This is primarily a learning/demonstration project, but contributions are welcome!
|
||||
**Golden Rule**: If it doesn't help QT6 Hello World, don't add it.
|
||||
|
||||
**Guidelines**:
|
||||
- Keep it minimal - every feature must justify its existence
|
||||
- Document your changes
|
||||
- Follow existing code style
|
||||
- Test on QEMU before submitting
|
||||
Contributions welcome for:
|
||||
- Simplifying existing code (make it smaller!)
|
||||
- Bug fixes
|
||||
- GPU driver work (hardest part)
|
||||
- QT6 port work
|
||||
- Documentation
|
||||
|
||||
See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for details.
|
||||
Not welcome:
|
||||
- Adding features "for completeness"
|
||||
- POSIX compatibility
|
||||
- Supporting other hardware
|
||||
- Generalizing anything
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/MINIMALISM.md](docs/MINIMALISM.md).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/*
|
||||
* MetalOS UEFI Bootloader
|
||||
*
|
||||
* This is a minimal UEFI bootloader that:
|
||||
* 1. Initializes graphics output
|
||||
* 2. Loads the kernel from disk
|
||||
* 3. Retrieves memory map and system information
|
||||
* 4. Exits boot services
|
||||
* 5. Transfers control to kernel
|
||||
* MINIMAL bootloader:
|
||||
* 1. Get framebuffer from UEFI
|
||||
* 2. Load kernel blob from disk
|
||||
* 3. Exit boot services
|
||||
* 4. Jump to kernel
|
||||
*
|
||||
* That's it. No fancy stuff.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
@@ -116,46 +117,35 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
||||
gST = SystemTable;
|
||||
|
||||
// Print banner
|
||||
print_string(u"MetalOS Bootloader v0.1.0\r\n");
|
||||
print_string(u"=========================\r\n\r\n");
|
||||
print_string(u"MetalOS v0.1 - MINIMAL BOOTLOADER\r\n");
|
||||
print_string(u"==================================\r\n\r\n");
|
||||
|
||||
// Initialize graphics
|
||||
print_string(u"Initializing graphics...\r\n");
|
||||
// Get framebuffer (don't care about resolution, take what UEFI gives us)
|
||||
print_string(u"Getting framebuffer...\r\n");
|
||||
status = initialize_graphics(ImageHandle);
|
||||
print_status(u"Graphics initialization", status);
|
||||
if (status != EFI_SUCCESS) {
|
||||
print_string(u"WARNING: Graphics initialization failed, continuing...\r\n");
|
||||
print_string(u"WARNING: No graphics, continuing anyway...\r\n");
|
||||
}
|
||||
|
||||
// Load kernel
|
||||
// Load kernel (just read metalos.bin, don't overthink it)
|
||||
print_string(u"Loading kernel...\r\n");
|
||||
status = load_kernel(ImageHandle);
|
||||
print_status(u"Kernel load", status);
|
||||
if (status != EFI_SUCCESS) {
|
||||
print_string(u"ERROR: Failed to load kernel\r\n");
|
||||
print_string(u"ERROR: Can't load kernel\r\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Get ACPI information
|
||||
print_string(u"Retrieving ACPI tables...\r\n");
|
||||
boot_info.rsdp = get_rsdp();
|
||||
// Get memory map (minimal info)
|
||||
print_string(u"Getting memory map...\r\n");
|
||||
// TODO: GetMemoryMap
|
||||
|
||||
// Get memory map
|
||||
print_string(u"Retrieving memory map...\r\n");
|
||||
// TODO: Call GetMemoryMap
|
||||
|
||||
// Exit boot services
|
||||
print_string(u"Exiting boot services...\r\n");
|
||||
// TODO: Call ExitBootServices
|
||||
// Exit boot services (point of no return)
|
||||
print_string(u"Exiting UEFI boot services...\r\n");
|
||||
// TODO: ExitBootServices
|
||||
|
||||
// Jump to kernel
|
||||
print_string(u"Starting kernel...\r\n");
|
||||
// TODO: ((void(*)(BootInfo*))KERNEL_LOAD_ADDRESS)(&boot_info);
|
||||
|
||||
// TODO: Call kernel entry point with boot_info
|
||||
// typedef void (*KernelEntry)(BootInfo*);
|
||||
// KernelEntry kernel = (KernelEntry)KERNEL_LOAD_ADDRESS;
|
||||
// kernel(&boot_info);
|
||||
|
||||
// If we get here, something went wrong
|
||||
// Should never get here
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ MetalOS is a ground-up operating system designed specifically to run QT6 applica
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Minimal by Design**: Only implement what's necessary to run QT6 applications
|
||||
1. **Absolute Minimum**: If it's not needed for QT6 Hello World, it doesn't exist
|
||||
2. **UEFI Native**: Boot directly via UEFI, no legacy BIOS support
|
||||
3. **Hardware Specific**: Optimized for AMD64 + Radeon RX 6600
|
||||
4. **Modern Approach**: Learn from Linux but implement cleanly from scratch
|
||||
3. **Hardware Specific**: AMD64 + Radeon RX 6600 only - no abstractions for other hardware
|
||||
4. **Single Purpose**: One app, one GPU, one goal - nothing else matters
|
||||
|
||||
## System Architecture
|
||||
|
||||
@@ -54,13 +54,13 @@ MetalOS is a ground-up operating system designed specifically to run QT6 applica
|
||||
- Transfer control to kernel
|
||||
|
||||
### 2. Kernel Core
|
||||
- **Purpose**: Provide essential OS services
|
||||
- **Language**: C/C++ with assembly for low-level operations
|
||||
- **Purpose**: Absolute bare minimum OS services
|
||||
- **Language**: C with assembly for critical parts
|
||||
- **Subsystems**:
|
||||
- Memory Management (physical/virtual)
|
||||
- Process/Thread Scheduler
|
||||
- Interrupt Handling
|
||||
- System Call Interface
|
||||
- Memory Management (just enough for app + QT6)
|
||||
- Single process support (no scheduler needed!)
|
||||
- Interrupt handling (only what GPU/input needs)
|
||||
- Direct syscall to kernel functions (no table/dispatch overhead)
|
||||
|
||||
### 3. Hardware Abstraction Layer (HAL)
|
||||
- **Purpose**: Abstract hardware specifics
|
||||
@@ -78,28 +78,29 @@ MetalOS is a ground-up operating system designed specifically to run QT6 applica
|
||||
- QT6 framework (statically linked into application)
|
||||
- No shell, no command line - direct boot to app
|
||||
|
||||
## Memory Layout
|
||||
## Memory Layout (Simplified)
|
||||
|
||||
```
|
||||
0x0000000000000000 - 0x0000000000000FFF : NULL guard page
|
||||
0x0000000000001000 - 0x00000000000FFFFF : Bootloader code/data
|
||||
0x0000000000100000 - 0x00000000FFFFFFFF : Kernel space
|
||||
0x0000000100000000 - 0x00007FFFFFFFFFFF : User space
|
||||
0xFFFF800000000000 - 0xFFFFFFFFFFFFFFFF : Kernel heap/stacks
|
||||
0x0000000000001000 - 0x00000000000FFFFF : Bootloader (temporary)
|
||||
0x0000000000100000 - 0x0000000000FFFFFF : Kernel (small!)
|
||||
0x0000000001000000 - 0x00000000FFFFFFFF : Application + QT6
|
||||
GPU VRAM: Separate, mapped via BAR
|
||||
```
|
||||
|
||||
## Boot Process
|
||||
No complex memory regions - keep it simple!
|
||||
|
||||
1. **UEFI Firmware** loads bootloader from EFI System Partition
|
||||
2. **Bootloader** initializes basic hardware and sets up memory
|
||||
3. **Bootloader** locates and loads kernel binary
|
||||
4. **Bootloader** exits UEFI boot services
|
||||
5. **Kernel** initializes subsystems (memory, scheduler, interrupts)
|
||||
6. **Kernel** loads HAL drivers (GPU, PCI, input)
|
||||
7. **Kernel** directly launches QT6 Hello World application (no shell, no init)
|
||||
8. **Application** runs full-screen until exit/reboot
|
||||
## Boot Process (Minimal)
|
||||
|
||||
**Note**: No command line, no shell - the system boots directly into the single application.
|
||||
1. **UEFI Firmware** loads bootloader
|
||||
2. **Bootloader** gets framebuffer, loads kernel, jumps
|
||||
3. **Kernel** maps memory, enables interrupts
|
||||
4. **Kernel** initializes GPU (minimal)
|
||||
5. **Kernel** sets up input (keyboard/mouse only)
|
||||
6. **Kernel** jumps directly to QT6 app
|
||||
7. **App** runs until halt
|
||||
|
||||
**That's it. No filesystem, no daemons, no services, no nothing.**
|
||||
|
||||
## Development Phases
|
||||
|
||||
|
||||
225
docs/MINIMALISM.md
Normal file
225
docs/MINIMALISM.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# MetalOS - Extreme Minimalism Guide
|
||||
|
||||
## What ABSOLUTE MINIMUM Means
|
||||
|
||||
We're not building a general-purpose OS. We're building **the smallest possible software layer** that lets QT6 Hello World run on AMD64 + RX 6600.
|
||||
|
||||
## Cut Everything
|
||||
|
||||
### ❌ NO Scheduler
|
||||
- **Why not?**: One app = one process = always running
|
||||
- **Instead**: Direct execution, no context switching
|
||||
- **Saves**: Scheduler code, process queues, timer interrupts for scheduling
|
||||
|
||||
### ❌ NO Process Management
|
||||
- **Why not?**: Only one process ever exists
|
||||
- **Instead**: App runs in ring 0 (kernel mode) or simple ring 3 with static setup
|
||||
- **Saves**: Process structures, fork/exec, process lifecycle
|
||||
|
||||
### ❌ NO File System
|
||||
- **Why not?**: Everything loaded at boot
|
||||
- **Instead**: App binary embedded in boot image or loaded by bootloader once
|
||||
- **Saves**: VFS, inode structures, file descriptors, read/write/open/close
|
||||
|
||||
### ❌ NO Networking
|
||||
- **Why not?**: Hello World doesn't need network
|
||||
- **Instead**: Nothing
|
||||
- **Saves**: TCP/IP stack, network drivers, sockets
|
||||
|
||||
### ❌ NO Security
|
||||
- **Why not?**: Single app, demo system
|
||||
- **Instead**: Trust everything
|
||||
- **Saves**: Permissions, user/group IDs, capabilities, security modules
|
||||
|
||||
### ❌ NO Virtual Memory (maybe)
|
||||
- **Why not?**: Could run everything with identity mapping
|
||||
- **Instead**: Simple page tables just to keep CPU happy
|
||||
- **Saves**: TLB management, page fault handling, swapping
|
||||
|
||||
### ❌ NO Dynamic Linking
|
||||
- **Why not?**: Complexity nightmare
|
||||
- **Instead**: Static link everything into one blob
|
||||
- **Saves**: ELF loader complexity, PLT/GOT, symbol resolution at runtime
|
||||
|
||||
### ❌ NO Multi-core
|
||||
- **Why not?**: One app on one core is plenty
|
||||
- **Instead**: Use only bootstrap processor (BSP)
|
||||
- **Saves**: SMP initialization, locks, atomic operations, IPI handling
|
||||
|
||||
### ❌ NO ACPI (mostly)
|
||||
- **Why not?**: Complex and usually not needed for basic operation
|
||||
- **Instead**: Minimal ACPI just for GPU if absolutely required
|
||||
- **Saves**: AML interpreter, ACPI tables parsing, power management
|
||||
|
||||
### ❌ NO Signals/IPC
|
||||
- **Why not?**: One process = nobody to talk to
|
||||
- **Instead**: Nothing
|
||||
- **Saves**: Signal handling, pipes, message queues, shared memory
|
||||
|
||||
### ❌ NO Timers (mostly)
|
||||
- **Why not?**: QT6 needs *some* time, but minimal
|
||||
- **Instead**: Simple timer for QT event loop only
|
||||
- **Saves**: Complex timer infrastructure, high-resolution timers
|
||||
|
||||
## What We MUST Keep (Absolute Minimum)
|
||||
|
||||
### ✅ Memory Allocator
|
||||
- **Why**: QT6 needs malloc/free
|
||||
- **Minimum**: Simple bump allocator or basic free list
|
||||
- **No need for**: Fancy algorithms, defragmentation, memory pools
|
||||
|
||||
### ✅ Interrupts
|
||||
- **Why**: Keyboard/mouse input, timer for QT
|
||||
- **Minimum**:
|
||||
- Keyboard interrupt
|
||||
- Mouse interrupt
|
||||
- Timer interrupt (for QT event loop)
|
||||
- GPU interrupt (if needed)
|
||||
- **That's it!** Maybe 4-5 interrupt handlers total
|
||||
|
||||
### ✅ GPU Driver
|
||||
- **Why**: Need to display graphics
|
||||
- **Minimum**:
|
||||
- Initialize display pipeline
|
||||
- Set up framebuffer
|
||||
- Blit pixels to screen
|
||||
- **No need for**: 3D acceleration, multiple displays, hot-plug
|
||||
|
||||
### ✅ Input Drivers
|
||||
- **Why**: Need keyboard/mouse for QT events
|
||||
- **Minimum**:
|
||||
- USB XHCI (or PS/2 if simpler!)
|
||||
- HID keyboard
|
||||
- HID mouse
|
||||
- **No need for**: Other USB devices, complex HID parsing
|
||||
|
||||
### ✅ PCI Enumeration
|
||||
- **Why**: Find the GPU
|
||||
- **Minimum**:
|
||||
- Scan bus for our specific GPU
|
||||
- Enable memory/IO access
|
||||
- **No need for**: Full PCI tree, hot-plug, PCI-to-PCI bridges
|
||||
|
||||
### ✅ System Calls (bare minimum)
|
||||
- **Why**: User space needs to talk to kernel
|
||||
- **Minimum**:
|
||||
- `write()` - for debugging output
|
||||
- `mmap()` - for memory
|
||||
- `ioctl()` - for GPU/input
|
||||
- Maybe 5-10 syscalls total
|
||||
- **No need for**: POSIX compatibility, 300+ syscalls
|
||||
|
||||
## Radical Simplifications
|
||||
|
||||
### Framebuffer Over Everything
|
||||
- **Skip**: Complex GPU 3D acceleration
|
||||
- **Use**: Direct framebuffer blitting
|
||||
- **QT6**: Can render to memory, we copy to VRAM
|
||||
- **Trade-off**: Slower but WAY simpler
|
||||
|
||||
### Identity Mapping (maybe)
|
||||
- **Skip**: Complex virtual memory
|
||||
- **Use**: Physical = Virtual (or simple offset)
|
||||
- **Note**: x86-64 requires paging enabled, but can be trivial
|
||||
|
||||
### PS/2 Over USB
|
||||
- **Skip**: Complex USB stack if possible
|
||||
- **Use**: PS/2 keyboard/mouse if hardware supports
|
||||
- **Simpler**: Direct port I/O vs USB protocol
|
||||
|
||||
### Polling Over Interrupts (where possible)
|
||||
- **Skip**: Complex interrupt handling
|
||||
- **Use**: Poll for events in tight loop
|
||||
- **Trade-off**: CPU usage vs complexity
|
||||
|
||||
### Hardcode Everything
|
||||
- **Skip**: Configuration files, boot parameters
|
||||
- **Use**: Compiled-in constants
|
||||
- **Examples**:
|
||||
- Screen resolution: 1920x1080 (hardcoded)
|
||||
- GPU PCI ID: hardcoded
|
||||
- Memory layout: hardcoded
|
||||
|
||||
## Code Size Targets
|
||||
|
||||
Aim for **minimal code size**:
|
||||
|
||||
- **Bootloader**: < 10 KB
|
||||
- **Kernel**: < 100 KB
|
||||
- **GPU Driver**: < 50 KB (hardest part)
|
||||
- **Input Drivers**: < 20 KB
|
||||
- **QT6 + App**: ~10-20 MB (unavoidable - QT is big)
|
||||
|
||||
**Total OS (without QT)**: ~200 KB or less!
|
||||
|
||||
## Performance Targets
|
||||
|
||||
We don't care about performance, we care about **working**:
|
||||
|
||||
- Boot time: Don't care (< 30 seconds is fine)
|
||||
- Frame rate: Don't care (30 FPS is plenty)
|
||||
- Memory usage: Don't care (512 MB is plenty)
|
||||
- CPU usage: Don't care (can peg one core)
|
||||
|
||||
**Trade complexity for simplicity every time.**
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Phase 1 ✅ (Done)
|
||||
- Project structure
|
||||
- Documentation
|
||||
|
||||
### Phase 2 (Bootloader)
|
||||
- UEFI console output (for debugging)
|
||||
- Load kernel blob
|
||||
- Jump to kernel
|
||||
- **Skip**: Complex file systems, just load from known location
|
||||
|
||||
### Phase 3 (Kernel)
|
||||
- Set up page tables (minimal)
|
||||
- Set up interrupts (only what we need)
|
||||
- Memory allocator (simple bump allocator)
|
||||
- **Skip**: Complex memory management
|
||||
|
||||
### Phase 4 (GPU)
|
||||
- PCI scan for RX 6600
|
||||
- Enable BAR
|
||||
- Initialize display (hardcode 1920x1080)
|
||||
- Framebuffer blit
|
||||
- **Skip**: Everything else GPU can do
|
||||
|
||||
### Phase 5 (Input)
|
||||
- Try PS/2 first (simpler!)
|
||||
- If not available, minimal USB XHCI
|
||||
- Keyboard scancodes -> QT key events
|
||||
- Mouse packets -> QT mouse events
|
||||
- **Skip**: Complex HID parsing, other devices
|
||||
|
||||
### Phase 6 (QT6)
|
||||
- Port minimal QT6 (Core + Gui + Widgets only)
|
||||
- QPA plugin: just framebuffer blit + input events
|
||||
- Static link everything
|
||||
- **Skip**: All optional QT modules
|
||||
|
||||
### Phase 7 (Integration)
|
||||
- Link app with QT6
|
||||
- Embed in boot image
|
||||
- Test and debug
|
||||
- **Skip**: Anything that doesn't work - iterate
|
||||
|
||||
## When in Doubt
|
||||
|
||||
Ask these questions:
|
||||
|
||||
1. **Does Hello World need this?** No → Cut it
|
||||
2. **Can we hardcode this?** Yes → Hardcode it
|
||||
3. **Can we do this simpler?** Yes → Do it simpler
|
||||
4. **Does Linux do it complex?** Yes → Do it simpler anyway
|
||||
|
||||
## Bottom Line
|
||||
|
||||
**Build the smallest possible OS that boots QT6 Hello World.**
|
||||
|
||||
If it doesn't directly contribute to that goal, it doesn't exist.
|
||||
|
||||
No compromises. Maximum minimalism.
|
||||
207
docs/ROADMAP.md
207
docs/ROADMAP.md
@@ -2,9 +2,11 @@
|
||||
|
||||
## Vision
|
||||
|
||||
MetalOS is a **minimal operating system** built from the ground up with a single purpose: run a QT6 Hello World application full-screen on AMD64 hardware with a Radeon RX 6600 GPU, booting via UEFI.
|
||||
MetalOS is **the absolute minimum operating system** needed to boot QT6 Hello World on AMD64 + RX 6600 via UEFI.
|
||||
|
||||
This is not a general-purpose OS. Every component is purpose-built to achieve this specific goal with minimal complexity.
|
||||
**Target**: < 200 KB of OS code (excluding QT6)
|
||||
|
||||
**Philosophy**: If it doesn't directly enable QT6 Hello World, it doesn't exist.
|
||||
|
||||
## Development Phases
|
||||
|
||||
@@ -28,145 +30,136 @@ This is not a general-purpose OS. Every component is purpose-built to achieve th
|
||||
|
||||
### Phase 2: UEFI Bootloader (Next)
|
||||
|
||||
**Goal**: Boot from UEFI and load kernel
|
||||
**Goal**: Load kernel and jump (< 10 KB code)
|
||||
|
||||
**Tasks**:
|
||||
1. Implement UEFI protocol interfaces
|
||||
- Console I/O for early debugging
|
||||
- Graphics Output Protocol
|
||||
- Simple File System Protocol
|
||||
- Memory allocation
|
||||
1. Console output for debugging (UEFI OutputString)
|
||||
2. Get framebuffer info from GOP (Graphics Output Protocol)
|
||||
3. Load kernel blob from known location
|
||||
4. Get minimal memory map
|
||||
5. Exit boot services
|
||||
6. Jump to kernel
|
||||
|
||||
2. Graphics initialization
|
||||
- Query available video modes
|
||||
- Set optimal resolution (1920x1080 or best available)
|
||||
- Set up framebuffer
|
||||
**Simplifications**:
|
||||
- Don't enumerate all video modes, take default
|
||||
- Don't parse filesystem, load from fixed location
|
||||
- Skip ACPI (try without it first)
|
||||
- No error recovery, just halt on failure
|
||||
|
||||
3. Kernel loading
|
||||
- Read metalos.bin from disk
|
||||
- Load into memory at 1MB mark
|
||||
- Verify kernel integrity
|
||||
|
||||
4. System information gathering
|
||||
- Get memory map
|
||||
- Find ACPI tables (RSDP)
|
||||
- Detect CPU features
|
||||
|
||||
5. Exit boot services and jump to kernel
|
||||
- Call ExitBootServices()
|
||||
- Pass BootInfo structure to kernel
|
||||
- Jump to kernel_main()
|
||||
|
||||
**Success Criteria**: Bootloader loads kernel and jumps to kernel code
|
||||
**Success Criteria**: Bootloader prints messages and jumps to kernel
|
||||
|
||||
### Phase 3: Minimal Kernel
|
||||
|
||||
**Goal**: Initialize hardware and provide basic services
|
||||
**Goal**: Initialize hardware (< 100 KB code)
|
||||
|
||||
**Tasks**:
|
||||
1. Early kernel initialization
|
||||
- Set up GDT (Global Descriptor Table)
|
||||
- Set up IDT (Interrupt Descriptor Table)
|
||||
- Enable interrupts
|
||||
- Initialize framebuffer console
|
||||
1. Minimal paging setup
|
||||
- Identity map or simple offset
|
||||
- Just enough to keep CPU happy
|
||||
- No fancy page fault handling
|
||||
|
||||
2. Memory management
|
||||
- Physical memory allocator (buddy system or bitmap)
|
||||
- Virtual memory setup (page tables)
|
||||
- Kernel heap allocator
|
||||
- *Minimal implementation - just enough for QT6*
|
||||
2. Interrupt handling
|
||||
- IDT with ~5 handlers max
|
||||
- Timer, keyboard, mouse, GPU (if needed)
|
||||
- No complex IRQ routing
|
||||
|
||||
3. Process/Thread support
|
||||
- Simple round-robin scheduler
|
||||
- Context switching (bare minimum)
|
||||
- Single user process support
|
||||
- *No multi-user, no fancy scheduling*
|
||||
3. Memory allocator
|
||||
- Bump allocator or simple free list
|
||||
- No fancy algorithms
|
||||
- Just malloc/free for QT6
|
||||
|
||||
4. Basic I/O
|
||||
- Serial port for debugging
|
||||
- Framebuffer console
|
||||
- *No disk I/O needed initially*
|
||||
4. NO scheduler - one process, always running
|
||||
5. NO process management - app is statically linked with kernel or simple jump
|
||||
|
||||
**Success Criteria**: Kernel boots, prints messages, can allocate memory
|
||||
**Simplifications**:
|
||||
- Skip GDT setup if not needed (UEFI might have set it up)
|
||||
- Identity mapping instead of complex virtual memory
|
||||
- Bump allocator instead of buddy/slab
|
||||
- No TLB shootdown, no page fault handling
|
||||
|
||||
### Phase 4: Hardware Abstraction Layer
|
||||
**Success Criteria**: Kernel boots, prints messages, mallocs work
|
||||
|
||||
**Goal**: Support minimal hardware needed for QT6
|
||||
### Phase 4: Hardware Support
|
||||
|
||||
**Goal**: GPU + Input (< 70 KB code)
|
||||
|
||||
**Tasks**:
|
||||
1. PCI Bus enumeration
|
||||
- Scan PCI devices
|
||||
- Find Radeon RX 6600 GPU
|
||||
- Basic configuration
|
||||
1. PCI scan (minimal)
|
||||
- Hardcode scan for vendor 0x1002 (AMD)
|
||||
- Find RX 6600 device ID
|
||||
- Enable memory access
|
||||
- That's it!
|
||||
|
||||
2. GPU Driver (Radeon RX 6600)
|
||||
- Initialize GPU
|
||||
- Set up display pipeline
|
||||
- Configure framebuffer
|
||||
- *Minimal - no 3D acceleration initially*
|
||||
- *Can use reference from Linux amdgpu driver*
|
||||
2. GPU Driver (hardest part, < 50 KB)
|
||||
- Map MMIO registers
|
||||
- Initialize display controller (DCN)
|
||||
- Hardcode 1920x1080 mode
|
||||
- Set up framebuffer in VRAM
|
||||
- Enable display output
|
||||
- *Study Linux amdgpu driver, but keep it simple*
|
||||
|
||||
3. Input devices
|
||||
- USB HID keyboard support
|
||||
- USB HID mouse support
|
||||
- PS/2 fallback (if needed)
|
||||
- *Just enough for QT event handling*
|
||||
3. Input devices (< 20 KB)
|
||||
- **Try PS/2 first** (much simpler than USB!)
|
||||
- If no PS/2: minimal USB XHCI for HID
|
||||
- Keyboard: scancode → QT key events
|
||||
- Mouse: packets → QT mouse events
|
||||
|
||||
4. Timer
|
||||
- APIC timer or PIT
|
||||
- For scheduling and timeouts
|
||||
**Simplifications**:
|
||||
- No PCI tree traversal, just scan for our GPU
|
||||
- No GPU 3D, just 2D framebuffer
|
||||
- No hot-plug, no multiple displays
|
||||
- PS/2 over USB if possible (way simpler)
|
||||
- No timer sophistication, PIT is fine
|
||||
|
||||
**Success Criteria**: Can detect and initialize GPU, receive keyboard/mouse input
|
||||
**Success Criteria**: Display working, keyboard/mouse input working
|
||||
|
||||
### Phase 5: System Call Interface
|
||||
### Phase 5: Minimal Syscalls
|
||||
|
||||
**Goal**: Provide user-kernel boundary
|
||||
**Goal**: User-kernel boundary (< 10 KB code)
|
||||
|
||||
**Tasks**:
|
||||
1. System call mechanism
|
||||
- syscall/sysret instructions
|
||||
- System call table
|
||||
- Parameter passing
|
||||
1. Syscall mechanism (syscall/sysret or just direct calls)
|
||||
2. Maybe 5-10 syscalls total:
|
||||
- write() - debugging
|
||||
- mmap() / munmap() - memory
|
||||
- ioctl() - device control
|
||||
- poll() - wait for input events
|
||||
- exit() - halt system
|
||||
|
||||
2. Essential system calls
|
||||
- exit() - terminate process
|
||||
- write() - output to console/log
|
||||
- mmap() - memory allocation
|
||||
- open/read/close() - minimal file operations (if needed)
|
||||
- ioctl() - device control (for GPU)
|
||||
- poll/select() - event handling (for input)
|
||||
**Simplifications**:
|
||||
- No syscall table if app can directly call kernel functions
|
||||
- No parameter validation (trust everything)
|
||||
- No error handling (just panic)
|
||||
|
||||
3. User-kernel transitions
|
||||
- Ring 3 to Ring 0 transitions
|
||||
- Parameter validation
|
||||
- Error handling
|
||||
**Success Criteria**: App can call kernel functions
|
||||
|
||||
**Success Criteria**: User space can make system calls
|
||||
### Phase 6: User Space & Application
|
||||
|
||||
### Phase 6: User Space Runtime
|
||||
|
||||
**Goal**: Support C++ applications
|
||||
**Goal**: Load and run app
|
||||
|
||||
**Tasks**:
|
||||
1. ELF loader
|
||||
- Parse ELF headers
|
||||
- Load program segments
|
||||
- Set up entry point
|
||||
- *Static linking initially - no dynamic loader*
|
||||
1. Simple app loading
|
||||
- Static-linked binary
|
||||
- No ELF parsing if we can avoid it
|
||||
- Just jump to known entry point
|
||||
|
||||
2. Minimal C/C++ runtime
|
||||
- _start() function
|
||||
- C++ global constructors/destructors
|
||||
- Memory allocation (malloc/free)
|
||||
- Basic string functions
|
||||
- *Only what QT6 needs*
|
||||
2. C++ minimal runtime
|
||||
- Global constructors
|
||||
- Basic new/delete (use kernel malloc)
|
||||
- No exceptions (disable them)
|
||||
|
||||
3. Application launcher (no init/shell needed)
|
||||
- Directly load QT6 hello world application
|
||||
- No command line, no shell
|
||||
- Single application until reboot
|
||||
3. Direct boot to app
|
||||
- No init, no shell
|
||||
- Kernel calls app's main() directly
|
||||
- App exits → kernel halts
|
||||
|
||||
**Success Criteria**: Can load and run the QT6 hello world application directly
|
||||
**Simplifications**:
|
||||
- Static link everything into one blob
|
||||
- Skip ELF loader completely if possible
|
||||
- No exceptions (compile with -fno-exceptions)
|
||||
- App runs in ring 0 or simple ring 3
|
||||
|
||||
**Success Criteria**: Can run simple C++ program
|
||||
|
||||
### Phase 7: QT6 Port
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* MetalOS Kernel - Main Entry Point
|
||||
*
|
||||
* Minimal kernel implementation for running QT6 applications.
|
||||
* Only implements what's absolutely necessary.
|
||||
* EXTREME MINIMAL kernel - only what's needed for QT6 Hello World.
|
||||
* No scheduler, no process management, no filesystem, no nothing.
|
||||
* Just: boot -> init GPU -> init input -> run app.
|
||||
*/
|
||||
|
||||
#include "kernel/kernel.h"
|
||||
@@ -11,6 +12,9 @@
|
||||
/*
|
||||
* Kernel main entry point
|
||||
* Called by bootloader with boot information
|
||||
*
|
||||
* This is it. The entire OS. No scheduler, no processes, no filesystem.
|
||||
* Just set up hardware and jump to the QT6 app.
|
||||
*/
|
||||
void kernel_main(BootInfo* boot_info) {
|
||||
// Initialize basic console output using framebuffer
|
||||
@@ -22,41 +26,55 @@ void kernel_main(BootInfo* boot_info) {
|
||||
);
|
||||
|
||||
console_clear();
|
||||
console_print("MetalOS Kernel v0.1.0\n");
|
||||
console_print("=====================\n\n");
|
||||
console_print("MetalOS v0.1 - MINIMAL\n");
|
||||
console_print("======================\n\n");
|
||||
|
||||
console_print("Initializing minimal kernel...\n");
|
||||
// TODO: Set up minimal page tables (identity mapped or simple offset)
|
||||
console_print("[ ] Memory (identity map)\n");
|
||||
|
||||
// TODO: Initialize memory management
|
||||
console_print("[ ] Memory management\n");
|
||||
// TODO: Set up IDT with only interrupts we need:
|
||||
// - Keyboard/mouse (USB or PS/2)
|
||||
// - Timer (for QT event loop)
|
||||
// - GPU (if needed)
|
||||
// That's it! Maybe 5 interrupt handlers total.
|
||||
console_print("[ ] Interrupts (minimal)\n");
|
||||
|
||||
// TODO: Initialize interrupt handling
|
||||
console_print("[ ] Interrupt handling\n");
|
||||
// TODO: Simple memory allocator (bump allocator is fine)
|
||||
console_print("[ ] Heap (bump allocator)\n");
|
||||
|
||||
// TODO: Initialize PCI bus
|
||||
console_print("[ ] PCI enumeration\n");
|
||||
// TODO: Find RX 6600 GPU via PCI (hardcode vendor/device ID)
|
||||
console_print("[ ] PCI (find GPU only)\n");
|
||||
|
||||
// TODO: Initialize GPU driver
|
||||
console_print("[ ] GPU driver (Radeon RX 6600)\n");
|
||||
// TODO: Initialize GPU - minimal
|
||||
// - Enable BAR
|
||||
// - Init display pipeline
|
||||
// - Set up framebuffer at 1920x1080 (hardcoded)
|
||||
console_print("[ ] GPU (RX 6600, 1920x1080)\n");
|
||||
|
||||
// TODO: Initialize input devices
|
||||
console_print("[ ] Input devices\n");
|
||||
// TODO: Initialize input
|
||||
// Try PS/2 first (simpler!)
|
||||
// Fall back to minimal USB XHCI if needed
|
||||
console_print("[ ] Input (PS/2 or USB)\n");
|
||||
|
||||
// TODO: Setup system calls
|
||||
console_print("[ ] System call interface\n");
|
||||
// TODO: Jump directly to QT6 Hello World app
|
||||
// No shell, no init, no fork/exec
|
||||
// Just: jump to application entry point
|
||||
console_print("[ ] Jump to QT6 app\n");
|
||||
|
||||
// TODO: Load and run QT6 hello world application directly (no shell/init)
|
||||
console_print("[ ] Loading QT6 Hello World application...\n");
|
||||
console_print("\nBooting app...\n");
|
||||
|
||||
console_print("\nKernel initialization complete.\n");
|
||||
console_print("Booting directly into application (no shell)...\n");
|
||||
// TODO: Replace this with jump to QT6 app
|
||||
// For now, halt
|
||||
console_print("ERROR: App not linked yet\n");
|
||||
|
||||
// TODO: Jump to QT6 hello world application entry point
|
||||
// The application will run full-screen until exit
|
||||
// No shell, no command line - just the one app
|
||||
|
||||
// Halt - in real implementation, we'd start the application
|
||||
while(1) {
|
||||
__asm__ volatile("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* That's the entire kernel. No scheduler. No processes. No filesystem.
|
||||
* Just boot, initialize hardware, run app.
|
||||
*
|
||||
* Total kernel size target: < 100 KB
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user