# LithosAnanke HAL Integration Guide ## Overview This document provides **kernel-specific implementation details** for the HAL platform layer that becomes LithosAnanke. It covers UEFI boot, freestanding C environment, hardware initialization, and the path to a working `ok` prompt. **Audience:** Kernel developers implementing `src/platform/kernel/` --- ## LithosAnanke Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ UEFI Firmware │ │ • Initializes hardware │ │ • Provides boot services (memory map, ACPI, GOP) │ │ • Loads BOOTX64.EFI │ └─────────────────────┬───────────────────────────────────────┘ │ ↓ ExitBootServices() ┌─────────────────────────────────────────────────────────────┐ │ LithosAnanke Boot Loader (stage 0) │ │ • Collects BootInfo (memory map, ACPI tables, framebuffer) │ │ • Sets up initial page tables │ │ • Exits UEFI boot services │ │ • Jumps to LithosAnanke proper │ └─────────────────────┬───────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────┐ │ LithosAnanke HAL (stage 1) │ │ • CPU initialization (GDT, IDT, interrupts) │ │ • Memory subsystem (PMM, VMM, heap) │ │ • Time subsystem (TSC, HPET, APIC timer) │ │ • Console (UART + framebuffer) │ └─────────────────────┬───────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────┐ │ StarForth VM │ │ • vm_create() │ │ • Initialize physics subsystems │ │ • Start REPL │ │ • Print "ok" prompt │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Directory Structure ``` src/platform/kernel/ ├── boot/ │ ├── uefi_loader.c # UEFI entry point (BOOTX64.EFI) │ ├── bootinfo.h # BootInfo struct definition │ └── handoff.S # ASM trampoline (UEFI → LithosAnanke) │ ├── cpu/ │ ├── gdt.c # Global Descriptor Table │ ├── idt.c # Interrupt Descriptor Table │ ├── isr.S # Interrupt service routine stubs │ └── smp.c # SMP bring-up (future) │ ├── mm/ │ ├── pmm.c # Physical Memory Manager │ ├── vmm.c # Virtual Memory Manager │ ├── kmalloc.c # Kernel heap allocator │ └── paging.S # Page table manipulation ASM │ ├── time/ │ ├── tsc.c # Time Stamp Counter │ ├── hpet.c # High Precision Event Timer │ ├── apic_timer.c # Local APIC timer │ └── pit.c # Programmable Interval Timer (fallback) │ ├── drivers/ │ ├── uart.c # UART 16550 serial console │ ├── framebuffer.c # UEFI GOP framebuffer │ ├── apic.c # Local APIC + IOAPIC │ ├── acpi.c # ACPI table parsing │ └── pci.c # PCI enumeration (future) │ ├── hal_time.c # HAL time implementation ├── hal_interrupt.c # HAL interrupt implementation ├── hal_memory.c # HAL memory implementation ├── hal_console.c # HAL console implementation ├── hal_cpu.c # HAL CPU implementation ├── hal_panic.c # HAL panic implementation │ └── kernel_main.c # LithosAnanke entry point (after UEFI) ``` --- ## Boot Sequence Detail ### 1. UEFI Loader (`boot/uefi_loader.c`) **Responsibilities:** - Collect system information from UEFI - Allocate kernel memory - Exit UEFI boot services - Jump to LithosAnanke **Implementation:** ```c /* boot/uefi_loader.c */ #include #include #include "bootinfo.h" /* BootInfo passed to LithosAnanke */ typedef struct { uint64_t memory_map_addr; uint64_t memory_map_size; uint64_t memory_map_descriptor_size; uint64_t acpi_rsdp_addr; uint64_t framebuffer_addr; uint32_t framebuffer_width; uint32_t framebuffer_height; uint32_t framebuffer_pitch; } BootInfo; EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); BootInfo *boot_info = (BootInfo *)AllocatePool(sizeof(BootInfo)); /* 1. Get memory map */ UINTN map_size = 0, map_key, descriptor_size; UINT32 descriptor_version; EFI_MEMORY_DESCRIPTOR *memory_map = NULL; uefi_call_wrapper(BS->GetMemoryMap, 5, &map_size, memory_map, &map_key, &descriptor_size, &descriptor_version); map_size += 2 * descriptor_size; /* Extra space for ExitBootServices */ memory_map = (EFI_MEMORY_DESCRIPTOR *)AllocatePool(map_size); uefi_call_wrapper(BS->GetMemoryMap, 5, &map_size, memory_map, &map_key, &descriptor_size, &descriptor_version); boot_info->memory_map_addr = (uint64_t)memory_map; boot_info->memory_map_size = map_size; boot_info->memory_map_descriptor_size = descriptor_size; /* 2. Get ACPI RSDP */ EFI_GUID acpi_20_guid = ACPI_20_TABLE_GUID; void *rsdp = NULL; for (UINTN i = 0; i < ST->NumberOfTableEntries; i++) { if (CompareGuid(&ST->ConfigurationTable[i].VendorGuid, &acpi_20_guid) == 0) { rsdp = ST->ConfigurationTable[i].VendorTable; break; } } boot_info->acpi_rsdp_addr = (uint64_t)rsdp; /* 3. Get framebuffer from GOP (Graphics Output Protocol) */ EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; uefi_call_wrapper(BS->LocateProtocol, 3, &gop_guid, NULL, (void **)&gop); if (gop) { boot_info->framebuffer_addr = gop->Mode->FrameBufferBase; boot_info->framebuffer_width = gop->Mode->Info->HorizontalResolution; boot_info->framebuffer_height = gop->Mode->Info->VerticalResolution; boot_info->framebuffer_pitch = gop->Mode->Info->PixelsPerScanLine * 4; } /* 4. Exit boot services */ uefi_call_wrapper(BS->ExitBootServices, 2, ImageHandle, map_key); /* 5. Jump to LithosAnanke */ extern void kernel_main(BootInfo *boot_info); kernel_main(boot_info); /* Never returns */ while (1) __asm__ volatile("hlt"); return EFI_SUCCESS; } ``` ### 2. LithosAnanke Entry Point (`kernel_main.c`) **Responsibilities:** - Parse BootInfo - Initialize CPU (GDT, IDT) - Initialize memory subsystem - Initialize HAL - Call `main()` to start VM **Implementation:** ```c /* kernel_main.c */ #include "bootinfo.h" #include "cpu/gdt.h" #include "cpu/idt.h" #include "mm/pmm.h" #include "mm/vmm.h" #include "drivers/uart.h" #include "drivers/framebuffer.h" /* Global BootInfo (available to all kernel code) */ BootInfo *g_boot_info = NULL; void kernel_main(BootInfo *boot_info) { g_boot_info = boot_info; /* 1. Initialize serial console ASAP (for debug output) */ uart_early_init(0x3F8, 115200); /* COM1 */ uart_puts("LithosAnanke booting...\r\n"); /* 2. Initialize CPU structures */ gdt_init(); idt_init(); /* 3. Initialize physical memory manager */ pmm_init(boot_info); uart_puts("PMM initialized\r\n"); /* 4. Initialize virtual memory manager */ vmm_init(); uart_puts("VMM initialized\r\n"); /* 5. Initialize kernel heap */ kmalloc_init(); uart_puts("Heap initialized\r\n"); /* 6. Initialize framebuffer */ fb_init(boot_info); /* 7. Initialize HAL */ hal_time_init(); hal_interrupt_init(); hal_mem_init(); hal_console_init(); hal_cpu_init(); uart_puts("HAL initialized\r\n"); /* 8. Call standard main() to start VM */ extern int main(int argc, char **argv); char *argv[] = {"starforth", NULL}; main(1, argv); /* Never returns, but halt if it does */ hal_panic("main() returned unexpectedly"); } ``` --- ## HAL Implementation Details ### 1. HAL Time (`hal_time.c`) **Hardware:** TSC (Time Stamp Counter), HPET (High Precision Event Timer), APIC timer **Key challenges:** - TSC calibration against HPET - TSC frequency varies on old CPUs (need invariant TSC check) - APIC timer setup for periodic interrupts **Implementation outline:** ```c /* hal_time.c */ #include "hal/hal_time.h" #include "time/tsc.h" #include "time/hpet.h" #include "time/apic_timer.h" static uint64_t tsc_hz = 0; static uint64_t boot_tsc = 0; void hal_time_init(void) { /* Check for invariant TSC */ if (!tsc_is_invariant()) { hal_panic("hal_time: TSC not invariant, falling back to HPET"); /* TODO: Use HPET directly if TSC unreliable */ } /* Calibrate TSC frequency using HPET */ tsc_hz = tsc_calibrate_hpet(); if (tsc_hz == 0) { hal_panic("hal_time: TSC calibration failed"); } boot_tsc = rdtsc(); /* Initialize APIC timer for periodic interrupts */ apic_timer_init(); } uint64_t hal_time_now_ns(void) { uint64_t tsc = rdtsc() - boot_tsc; return (tsc * 1000000000ULL) / tsc_hz; } int hal_timer_periodic(uint64_t period_ns, hal_timer_callback_t callback, void *ctx) { return apic_timer_periodic(period_ns, callback, ctx); } ``` **See:** `time/tsc.c`, `time/hpet.c`, `time/apic_timer.c` for low-level implementations. --- ### 2. HAL Interrupt (`hal_interrupt.c`) **Hardware:** IDT (Interrupt Descriptor Table), Local APIC, IOAPIC **Key challenges:** - Setting up 256 IDT entries - Routing hardware IRQs through IOAPIC - Tracking interrupt nesting depth (for `hal_in_interrupt_context()`) **Implementation outline:** ```c /* hal_interrupt.c */ #include "hal/hal_interrupt.h" #include "cpu/idt.h" #include "drivers/apic.h" /* Per-CPU interrupt depth (thread-local on SMP) */ static __thread unsigned int irq_depth = 0; void hal_interrupt_init(void) { /* Set up IDT with 256 entries */ idt_init(); /* Disable legacy PIC (use APIC instead) */ outb(0x21, 0xFF); /* Mask all PIC1 IRQs */ outb(0xA1, 0xFF); /* Mask all PIC2 IRQs */ /* Initialize Local APIC */ apic_init(); /* Initialize IOAPIC */ ioapic_init(); } void hal_irq_enable(void) { __asm__ volatile("sti"); } unsigned long hal_irq_disable(void) { unsigned long flags; __asm__ volatile("pushfq; popq %0; cli" : "=r"(flags)); return flags; } void hal_irq_restore(unsigned long flags) { __asm__ volatile("pushq %0; popfq" :: "r"(flags)); } int hal_in_interrupt_context(void) { return irq_depth > 0; } /* Common ISR entry (called from IDT stubs) */ void isr_common_handler(uint64_t vector, uint64_t error_code) { irq_depth++; /* Dispatch to registered handler */ extern void isr_dispatch(uint64_t vector, uint64_t error_code); isr_dispatch(vector, error_code); irq_depth--; /* Send EOI to APIC */ apic_eoi(); } ``` **See:** `cpu/idt.c`, `cpu/isr.S`, `drivers/apic.c` for low-level implementations. --- ### 3. HAL Memory (`hal_memory.c`) **Components:** - **PMM (Physical Memory Manager):** Tracks free/used physical page frames - **VMM (Virtual Memory Manager):** Manages page tables (4-level paging on x86_64) - **kmalloc:** Kernel heap allocator (slab or buddy allocator) **Implementation outline:** ```c /* hal_memory.c */ #include "hal/hal_memory.h" #include "mm/pmm.h" #include "mm/vmm.h" #include "mm/kmalloc.h" void hal_mem_init(void) { /* PMM and VMM initialized in kernel_main() before HAL */ /* Just verify they're ready */ if (!pmm_is_initialized()) { hal_panic("hal_mem_init: PMM not initialized"); } } void *hal_mem_alloc(size_t size) { return kmalloc(size); } void hal_mem_free(void *ptr) { kfree(ptr); } uint64_t hal_mem_alloc_pages(size_t count) { return pmm_alloc_pages(count); } void hal_mem_free_pages(uint64_t paddr, size_t count) { pmm_free_pages(paddr, count); } int hal_mem_map(uint64_t vaddr, uint64_t paddr, size_t size, unsigned int flags) { return vmm_map_range(vaddr, paddr, size, flags); } size_t hal_mem_page_size(void) { return 4096; } ``` **PMM details** (`mm/pmm.c`): - Bitmap allocator (1 bit per 4KB page) - Parse UEFI memory map to mark usable vs. reserved regions - Reserve kernel image, ACPI tables, framebuffer **VMM details** (`mm/vmm.c`): - 4-level page tables (PML4 → PDPT → PD → PT) - Recursive mapping trick for page table access - Identity-map kernel, higher-half kernel optional **kmalloc details** (`mm/kmalloc.c`): - Slab allocator for common sizes (16, 32, 64, ..., 4096 bytes) - Buddy allocator for large allocations - Zero-initialization required by HAL contract --- ### 4. HAL Console (`hal_console.c`) **Hardware:** UART 16550 (serial), UEFI GOP framebuffer (video) **Implementation outline:** ```c /* hal_console.c */ #include "hal/hal_console.h" #include "drivers/uart.h" #include "drivers/framebuffer.h" void hal_console_init(void) { /* UART already initialized in kernel_main() for early debug */ /* Framebuffer initialized from BootInfo */ } void hal_console_putc(char c) { uart_putc(c); /* Always output to serial */ fb_putc(c); /* Also output to framebuffer if available */ } void hal_console_puts(const char *s) { while (*s) { hal_console_putc(*s++); } } int hal_console_getc(void) { /* Block until UART has data */ return uart_getc(); } int hal_console_has_input(void) { return uart_has_data(); } ``` **UART details** (`drivers/uart.c`): - 16550 compatible (COM1 = 0x3F8, COM2 = 0x2F8) - 115200 baud default - Polling mode (no interrupts for simplicity) **Framebuffer details** (`drivers/framebuffer.c`): - Linear framebuffer from UEFI GOP - 32-bit RGB pixels - Software text rendering (8x16 font) - Scrolling, cursor, ANSI escape codes (optional) --- ### 5. HAL CPU (`hal_cpu.c`) **Implementation outline:** ```c /* hal_cpu.c */ #include "hal/hal_cpu.h" #include "drivers/apic.h" static unsigned int num_cpus = 1; void hal_cpu_init(void) { /* Detect CPU features (CPUID) */ /* TODO: Bring up secondary CPUs (SMP) */ } unsigned int hal_cpu_id(void) { return apic_get_id(); /* Local APIC ID */ } void hal_cpu_relax(void) { __asm__ volatile("pause"); } void hal_cpu_halt(void) { __asm__ volatile("hlt"); } unsigned int hal_cpu_count(void) { return num_cpus; } ``` --- ## Build System ### Toolchain Requirements **Freestanding C environment:** - `gcc` or `clang` with `-ffreestanding` - `ld` with custom linker script - `objcopy` to create PE32+ executable (for UEFI) ### Makefile Additions ```makefile # Platform: kernel ifeq ($(PLATFORM),kernel) CC = gcc LD = ld OBJCOPY = objcopy CFLAGS += -ffreestanding -nostdlib -mno-red-zone -mcmodel=large CFLAGS += -mno-mmx -mno-sse -mno-sse2 # No FP in kernel CFLAGS += -I/usr/include/efi -I/usr/include/efi/x86_64 LDFLAGS += -nostdlib -static -T src/platform/kernel/linker.ld # Platform sources PLATFORM_SOURCES = \ src/platform/kernel/boot/uefi_loader.c \ src/platform/kernel/kernel_main.c \ src/platform/kernel/cpu/gdt.c \ src/platform/kernel/cpu/idt.c \ src/platform/kernel/cpu/isr.S \ src/platform/kernel/mm/pmm.c \ src/platform/kernel/mm/vmm.c \ src/platform/kernel/mm/kmalloc.c \ src/platform/kernel/drivers/uart.c \ src/platform/kernel/drivers/framebuffer.c \ src/platform/kernel/drivers/apic.c \ src/platform/kernel/hal_time.c \ src/platform/kernel/hal_interrupt.c \ src/platform/kernel/hal_memory.c \ src/platform/kernel/hal_console.c \ src/platform/kernel/hal_cpu.c \ src/platform/kernel/hal_panic.c # Build UEFI PE32+ executable starforth.efi: $(OBJECTS) $(LD) $(LDFLAGS) -o starforth.so $(OBJECTS) $(OBJCOPY) -j .text -j .data -j .rodata -j .reloc \ --target=efi-app-x86_64 starforth.so $@ endif ``` ### Linker Script (`src/platform/kernel/linker.ld`) ```ld OUTPUT_FORMAT("elf64-x86-64") ENTRY(efi_main) SECTIONS { . = 0x100000; /* Load at 1MB (standard kernel load address) */ .text : { *(.text .text.*) } .rodata : { *(.rodata .rodata.*) } .data : { *(.data .data.*) } .bss : { *(COMMON) *(.bss .bss.*) } /DISCARD/ : { *(.eh_frame) } } ``` --- ## Testing on QEMU ### QEMU + OVMF Setup ```bash # Install OVMF (UEFI firmware for QEMU) sudo apt install ovmf # Create ESP (EFI System Partition) mkdir -p esp/EFI/BOOT cp starforth.efi esp/EFI/BOOT/BOOTX64.EFI # Run QEMU qemu-system-x86_64 \ -bios /usr/share/ovmf/OVMF.fd \ -drive file=fat:rw:esp/,format=raw \ -serial stdio \ -m 512M \ -enable-kvm ``` ### Expected Output ``` LithosAnanke booting... PMM initialized VMM initialized Heap initialized HAL initialized StarForth VM v1.0 ok ``` --- ## Debugging ### Serial Debugging ```c /* Early debug output via UART */ void debug_puts(const char *s) { while (*s) { while (!(inb(0x3FD) & 0x20)); /* Wait for UART ready */ outb(0x3F8, *s++); /* Write character */ } } ``` ### GDB Remote Debugging ```bash # Start QEMU with GDB server qemu-system-x86_64 ... -s -S # In another terminal gdb starforth.elf (gdb) target remote :1234 (gdb) break kernel_main (gdb) continue ``` ### Panic Handler ```c /* hal_panic.c */ void hal_panic(const char *msg) { hal_irq_disable(); hal_console_puts("\n*** KERNEL PANIC ***\n"); hal_console_puts(msg ? msg : "unknown error"); hal_console_puts("\nSystem halted.\n"); /* Halt all CPUs */ while (1) { hal_cpu_halt(); } } ``` --- ## Roadmap to `ok` Prompt ### Milestone 1: Boot + Serial Output - UEFI loader runs - Kernel prints "LithosAnanke booting..." to serial - System doesn't triple-fault ### Milestone 2: Memory Works - PMM tracks physical pages - VMM maps kernel - kmalloc/kfree work ### Milestone 3: HAL Initialized - All `hal_*_init()` functions complete - HAL functions callable (even if not fully functional) ### Milestone 4: VM Starts - `vm_create()` succeeds - Dictionary allocated - No crashes in VM init ### Milestone 5: REPL Runs - REPL prints "`ok`" prompt - Can type characters (echoed to serial) - Can execute simple words (`1 2 + .` → `3`) ### Milestone 6: Physics Subsystems Work - Execution heat tracking operational - Heartbeat timer fires - Rolling window captures execution history ### Milestone 7: Full Test Suite - All 936+ tests pass on kernel - DoE mode works - 0% algorithmic variance on bare metal --- ## Future Work (StarshipOS) After achieving `ok` prompt on LithosAnanke: 1. **Storage:** AHCI/NVMe drivers, FAT32 filesystem 2. **Networking:** VirtIO-net driver, TCP/IP stack 3. **Process model:** Forth tasks, scheduling, IPC 4. **Device model:** Unified block/net/char subsystem 5. **Security:** Capabilities, ACL, Forth-based access control **The HAL remains the foundation throughout.** --- ## References - UEFI Specification: https://uefi.org/specifications - GNU-EFI: https://sourceforge.net/projects/gnu-efi/ - OSDev Wiki: https://wiki.osdev.org/ - Intel SDM: https://www.intel.com/sdm - ACPI Specification: https://uefi.org/acpi