Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
Atomic-x86
==========
============================================================
STATUS
============================================================
This project is currently incomplete and is not under active
development. Development has been temporarily placed on hold
and may resume at a later date.
The current version should be considered a work in progress
and may contain incomplete features or functionality.
============================================================
This is the source for mini-kernel (also called atomic-x86), a small x86
operating system kernel written in C and NASM assembly. I built this as a
experiment for my first old PC to exp with low-level systems programming.
Built without any standard library, OS support, or outside dependencies -
just a cross-compiler, an assembler, and the metal.
Target: i686 (32-bit x86), Multiboot 1, ELF binary, loaded at physical
address 0x100000.
Overview
--------
mini-kernel boots via GRUB (Multiboot 1), enters 32-bit protected mode,
and sets up a complete foundational kernel layer:
Boot - GRUB multiboot header, stack setup, ISR/IRQ assembly stubs
CPU - GDT flat model, IDT with 256 gates, exception + hardware IRQ dispatch
Drivers - VGA text output, PS/2 keyboard (IRQ 1), PS/2 mouse (IRQ 12),
PIT timer at 100 Hz (IRQ 0), serial port (COM1), ATA disk (PIO)
Memory - Bitmap physical frame allocator, identity-mapped paging, kernel heap
Library - memset/memcpy/strcmp/strncmp, kprintf with %c %s %d %u %x %p,
port I/O inlines, random number generator
Shell - Interactive command interface - help, mem, uptime, echo, color,
version, reboot, panic_test, pci, date, shutdown, trace, dev,
loopback, ata, mouse
PCI - Scans the PCI bus and lists all devices found
Time - Reads the real-time clock (RTC) from CMOS, tracks uptime
Block - Generic block device layer so disk drivers all look the same
DevFS - Device files under /dev like null, zero, random, ata0, ttyS0
ACPI - Reads the ACPI tables and can shut down the computer properly
Net - Loopback network interface for testing packets
Debug - Stack trace dump (ktrace) and assert macros
The kernel is entirely interrupt-driven after init. After boot it drops into
an interactive shell - type commands and the kernel responds in real time.
Folder Layout
-------------
boot/ - boot.asm (multiboot header, stack, calls kernel_main)
kernel_entry.asm (ISR/IRQ assembly stubs)
cpu/ - gdt.c, gdt.h, gdt_flush.asm
idt.c, idt.h, idt_flush.asm
isr.c, isr.h (CPU exceptions 0-31)
irq.c, irq.h (PIC remap, hardware IRQs 0-15)
syscall_stub.asm (int 0x80 handler)
drivers/ - vga.c/h (text mode framebuffer 0xB8000)
keyboard.c/h (PS/2 keyboard, IRQ 1)
mouse.c/h (PS/2 mouse, IRQ 12)
timer.c/h (PIT 8253/8254 at 100 Hz)
serial.c/h (COM1 UART at 0x3F8)
ata.c/h (ATA primary master, PIO mode LBA28)
kernel/ - main.c (init sequence, never returns)
kernel.h (types, macros, port I/O, multiboot struct)
shell.c/h (interactive command shell)
panic.c/h (red screen of death, register dump, halt)
cpp_runtime.c/h (C++ global constructor runner)
mm/ - pmm.c/h (bitmap physical memory allocator)
paging.c/h (identity map + on-demand page mapping)
kmalloc.c/h (kernel heap, bump + free list)
lib/ - string.c/h (strlen, strcmp, memcpy, memset, strncmp)
kprintf.c/h (kernel printf, writes to VGA)
rand.c/h (simple LCG random number generator)
task/ - scheduler.c/h (round-robin task switching)
process.c/h (create and destroy tasks)
context_switch.asm (low-level switch helper)
fs/ - vfs.c/h (virtual filesystem layer)
tmpfs.c/h (ramdisk filesystem)
sys/ - syscall.c/h (system call table, int 0x80)
pci/ - pci.c/h (PCI bus scanner, reads config space)
time/ - rtc.c/h (CMOS real-time clock reader)
timekeeper.c/h (tracks boot time and uptime)
block/ - block.c/h (generic block device abstraction)
dev/ - devfs.c/h (device files: /dev/null, /dev/zero, etc)
acpi/ - acpi.c/h (ACPI RSDP parser, shutdown support)
net/ - netif.c/h (network interface layer)
loopback.c/h (loopback interface for testing)
ethernet.h (Ethernet frame header)
debug/ - ktrace.c/h (stack trace unwinder)
assert.h (ASSERT and ASSERT_MSG macros)
scripts/ - build_iso.sh (makes a bootable ISO with GRUB)
Prerequisites
-------------
Ubuntu / Debian:
sudo apt update
sudo apt install -y \
gcc-i686-linux-gnu \
binutils \
nasm \
qemu-system-x86 \
grub-pc-bin \
xorriso \
mtools
# If your Makefile uses i686-elf-gcc, change it to i686-linux-gnu-gcc
macOS (Homebrew):
brew install i686-elf-gcc i686-elf-binutils nasm qemu xorriso
Verify your toolchain:
i686-elf-gcc --version
nasm --version
qemu-system-i386 --version
grub-mkrescue --version
Building
--------
cd mykernel
# Compile all sources -> mini-kernel.bin (ELF)
make
# Wrap in a GRUB-bootable ISO -> mini-kernel.iso
./scripts/build_iso.sh
# Wipe all object files and outputs
make clean
Running
-------
# Build and launch QEMU
make run
# Run the ISO manually
qemu-system-i386 -cdrom mini-kernel.iso
# Run the raw ELF binary (QEMU acts as bootloader)
qemu-system-i386 -kernel mini-kernel.bin
# With 128 MB RAM and serial output to terminal
qemu-system-i386 -cdrom mini-kernel.iso -m 128M -serial stdio
# With mouse support (for testing the PS/2 mouse driver)
qemu-system-i386 -cdrom mini-kernel.iso -m 128M -serial stdio -usbdevice mouse
Verify the binary before running:
i686-elf-readelf -h mini-kernel.bin
grub-file --is-x86-multiboot mini-kernel.bin && echo "multiboot OK"
i686-elf-objdump -d mini-kernel.bin | head -40
Debugging with GDB
------------------
Launch QEMU with GDB stub and freeze CPU at boot:
qemu-system-i386 -kernel mini-kernel.bin -s -S
In another terminal, attach GDB:
gdb mini-kernel.bin
(gdb) target remote :1234
(gdb) break kernel_main
(gdb) continue
Useful GDB commands:
info registers Dump all CPU registers
x/10i $eip Disassemble 10 instructions at EIP
x/16xw 0xB8000 Inspect VGA framebuffer
break panic Break on kernel panic
set architecture i386 Ensure 32-bit mode
Boot Sequence
-------------
1. vga_init() - console first, so kprintf works
2. verify magic - confirm GRUB handshake
3. gdt_init() - flat segment model
4. idt_init() - 256-gate descriptor table
5. isr_init() - install exception stubs 0-31
6. irq_init() - remap PIC, install IRQ stubs 32-47
7. pmm_init(mbi) - parse GRUB memory map
8. paging_init() - identity map 0-4 MB, enable CR0.PG
9. kmalloc_init() - set up kernel heap at 0x400000
10. timer_init(100) - PIT at 100 Hz
11. keyboard_init() - PS/2 keyboard driver on IRQ 1
12. mouse_init() - PS/2 mouse driver on IRQ 12
13. ata_init() - detect primary master ATA disk
14. serial_init() - setup COM1 serial port
15. pci_init() - scan PCI bus for devices
16. timekeeper_init()- read RTC and start uptime counter
17. block_init() - setup block device layer
18. devfs_init() - create /dev/null, /dev/zero, etc
19. acpi_init() - parse ACPI tables for shutdown
20. net_init() - setup loopback network interface
21. srand() - seed random number generator
22. sti - interrupts enabled (last)
└─ shell_run() - interactive shell, never returns
Memory Layout
-------------
0x00000000 BIOS data, real-mode IVT (reserved)
0x00100000 kernel load address (1 MB)
.text code
.rodata read-only data
.data initialised globals
.bss uninitialised - stack (16 KB), page directory,
page table, PMM bitmap
kernel_end linker symbol
0x00400000 kernel heap base
0x00800000 kernel heap ceiling
Virtual == Physical 0x000000 - 0x3FFFFF identity-mapped (first 4 MB)
Heap pages 0x400000+ mapped on demand by kmalloc
Shell Commands
--------------
help show all commands and what they do
clear wipe the screen
mem show free physical memory in frames, KB and MB
uptime show time since boot in hours:minutes:seconds
echo <text> print text back to the screen
color <name> change text color (white, green, cyan, red, blue, etc)
version show kernel version and build date
reboot reboot the computer via keyboard controller or triple fault
panic_test trigger a test kernel panic (for debugging)
pci list all PCI bus devices found
date show RTC time and uptime in milliseconds
shutdown power off the computer using ACPI
trace print a stack trace of the current call stack
dev list all files under /dev
loopback send a test packet through the loopback interface
ata read sector 0 from the ATA disk and show first 16 bytes
mouse show 10 mouse movement events (move mouse to see output)
Extending the Kernel
--------------------
New shell commands - add a cmd_entry_t to cmds[] in shell.c
ELF loader - add code to read ELF binaries from disk and run them
User mode (ring 3) - add user GDT entry (DPL=3), TSS, iret into ring 3
Higher-half kernel - remap kernel to 0xC0100000 in page directory
ext2 filesystem - add a read-only ext2 driver on top of the block layer
Real network card - add RTL8139 or NE2000 driver for real packets
VESA graphics - switch from text mode to framebuffer graphics
USB support - add UHCI/OHCI controller driver
References
----------
OSDev Wiki
https://wiki.osdev.org
Intel 64 and IA-32 Architectures Software Developer Manuals
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
Multiboot Specification
https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
8259 PIC datasheet
https://pdos.csail.mit.edu/6.828/2014/readings/hardware/8259A.pdf
8253/8254 PIT datasheet
https://www.scs.stanford.edu/10wi-cs140/pintos/specs/8254.pdf
James Molloy's kernel tutorial
http://www.jamesmolloy.co.uk/tutorial_html/
License
-------
MIT License. See LICENSE file for details.