Architecture & Boot
Contents[hide] |
Kernel topology
nexOS is monolithic: bootloader, kernel, ATA/FAT32 storage, RTL8139 networking, and the entire GUI are linked into a single flat image that runs at privilege level 0. There is no kernel/userspace split and no module loading. “Applications” (Paint, terminal, browser, file manager) are C functions called from main().
+------------------------------+
| nexos.img (32 KiB raw) |
+--------------+----------------+
| sector 0 | sectors 1..63 |
| boot.asm | kernel.bin |
| (512 B) | (objcopy) |
+------+-------+----------------+
| BIOS INT 13h, 60 sectors to 0x8000
v
+--------------+ +---------------------------+
| boot.asm | | kernel (flat, ring 0) |
| real mode | | _start -> _main -> main() |
| -> prot.mode | | paging + drivers + GUI |
+--------------+ +---------------------------+
Entry-point chain
Three symbols stand between the CPU and the first line of C:
[boot.asm] init_pm: call 0x8000 ; KERNEL_OFFSET
|
v
[kernel_entry.asm] _start:
call _main ; extern _main (kernel.c)
jmp $ ; halt if it ever returns
|
v
[kernel.c] void _main(void) { main(); }
|
v
[kernel.c] void main(void) { ... } ; page_init, drivers, GUI loop
main() initializes in order: net_init(), vbe_init(), init_font(), boot_splash(), remap_pic(), init_idt(), init_ps2(), pit_init(), then sti and the desktop loop. Paging is enabled early via page_init() (see Memory).
Bootloader (boot.asm)
Assembled with nasm -f bin into sector 0 (154 lines). It does four jobs:
- Zero segment registers, set sp = 0x7C00, save dl in BOOT_DRIVE.
- Load the kernel — BIOS INT 13h AH=0x02, AL=60 sectors from CHS (0,0,2) to 0x8000. 60 sectors covers the grown kernel (~42 sectors after FAT32+network were added; the old 40-sector read truncated it). On error it writes 0x4F52 to text VRAM 0xB8000 and halts.
- Set video mode — VESA 0x4F01/0x4F02 with LFB bit 0x4000, copy result to VBE_OUT @ 0x5000.
- Enter protected mode — lgdt, set CR0.PE, far jump 0x08:init_pm, load data selector, ebp = esp = 0x1000000 (16 MiB, up from the old 0x90000).
VESA mode preference order
The bootloader tries modes best-first, then falls back to VGA mode 13h:
vesa_modes: dw 0x118, 0x11B, 0x115, 0x114, 0x112, 0x111, 0 ; 0x118 = 1024x768x24bpp first, then 0x11B, then 800x600 (0x115/0x114), ; then 640x480 (0x112/0x111). QEMU is run with -vga vmware so the ; high modes probe successfully; bare hardware falls back gracefully. vesa_fail: ; fallback VGA 320x200x8bpp mov ah,0x00 / mov al,0x13 ; INT 10h mode 13h LFB = 0xA0000, 320x200, pitch 320, bpp 8
GDT — flat model
Three-entry GDT, 4 GiB flat space for code and data (base 0, limit 0xFFFFF, 4 KiB granularity):
| Index | Selector | Base | Limit | Access | Flags |
|---|---|---|---|---|---|
| 0 | — | 0x0 | 0x0 | 0x00 | 0x0 |
| 1 (code) | 0x08 | 0x0 | 0xFFFFF | 10011010b (0x9A) | 11001111b (0xCF) |
| 2 (data) | 0x10 | 0x0 | 0xFFFFF | 10010010b (0x92) | 11001111b (0xCF) |
Selector 0x08 is also the IDT gate code selector; 0x10 loads DS/SS/ES/FS/GS. Paging builds on top of this flat segmentation (see Memory).
Memory map
0x1000000 +------------------+ protected-mode stack top (16 MiB)
| kernel stack |
0x080000...+------------------+ page tables (aligned 4 KiB) + heap pages
0x00200000 +------------------+ BACKBUFFER_ADDR (off-screen frame)
0x00080000 +------------------+ KERNEL_OFFSET / link . = 0x8000 (.text/.data/.bss)
0x00007C00 +------------------+ bootloader (512 B, org 0x7C00)
0x00000600 +------------------+ MODE_INFO (VBE info buffer)
0x00000500 +------------------+ VBE_OUT (16-byte param block)
| IVT / BIOS data |
0x00000000 +------------------+
0xA0000 VGA 13h fallback LFB | 0xB8000 text VRAM (disk_error)
The 16-byte VBE_OUT block is the only bootloader→kernel IPC. It is read by vbe_init() — see Memory for offsets.