Skip to main content
← [ ABORT TO HUD ]
SEQ. 1
SEQ. 2

#![no_std] Rust, Paging & Hardware Interrupts (IDT)

🖥️ Bare-Metal & Kernel Engineering (The Freedom OS Architecture)⏱ 20 min⭐ 150 BASE XP⌨ HANDS-ON LAB

The Philosophy of Freedom OS

Freedom OS (30 Rust kernel modules, zero external dependencies, UEFI boot, custom GUI window compositor, integrated NexusCode IDE, and in-kernel TCP/IP stack) is an open-source bare-metal operating system written from scratch in #![no_std] Rust. In this environment, there is no libc, no OS thread scheduler, and no host runtime—you program directly against bare-metal x86_64 silicon.

Disabling the Runtime & Handling Panics

#![no_std]
#![no_main]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    // Print panic message directly to serial port or VGA memory
    unsafe {
        write_vga_error("KERNEL PANIC: Unrecoverable CPU fault");
    }
    loop {
        // Halt CPU to prevent execution runaway
        x86_64::instructions::hlt();
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn _start() -> ! {
    // Entry point invoked by bootloader
    init_gdt();
    init_idt();
    unsafe { init_page_tables(); }
    
    loop {
        x86_64::instructions::hlt();
    }
}

UEFI Boot Handoff & 4-Level x86_64 Paging (PML4 → PDPT → PD → PT)

In modern uefi (v0.33+ through 2026 releases), the legacy SystemTable<Boot> entry parameter was removed in favor of global freestanding boot helpers. Exiting boot services returns an owned physical memory map while fencing off invalid boot-time protocols:

use uefi::prelude::*;
use uefi::mem::memory_map::MemoryMapOwned;

#[entry]
fn efi_main() -> Status {
    // Locate GOP framebuffer before exiting UEFI Boot Services...
    // Safely exit boot services (None defaults to MemoryType::LOADER_DATA)
    let memory_map: MemoryMapOwned = unsafe { uefi::boot::exit_boot_services(None) };
    kernel_handoff(memory_map)
}

Once in 64-bit Long Mode, physical register CR3 points to the 512-entry Page-Map Level-4 (PML4) table. Every canonical 48-bit virtual address translates through four 9-bit page-table indices (PML4[47:39] → PDPT[38:30] → PD[29:21] → PT[20:12]) plus a 12-bit offset (4 KiB frames, or 2 MiB / 1 GiB huge pages), isolating kernel space alongside the GDT and Local APIC / IOAPIC interrupt controllers.

Interrupt Descriptor Table (IDT) Configuration

When a hardware timer fires or a page fault occurs, the CPU jumps to a vector table indexed by the IDT. Rust handles this cleanly through the x86-interrupt ABI:

extern "x86-interrupt" fn page_fault_handler(
    stack_frame: InterruptStackFrame,
    error_code: PageFaultErrorCode,
) {
    let fault_address = x86_64::registers::control::Cr2::read();
    serial_println!("PAGE FAULT at {:#x}, error: {:?}", fault_address, error_code);
    loop { x86_64::instructions::hlt(); }
}
⌨ HANDS-ON LABBoot Bare-Metal Kernel in QEMU with UART Serial Output
⭐ +170 XP

Compile a #![no_std] Rust kernel, build an ELF image, and boot inside the QEMU x86_64 virtualization sandbox.

1Build the bare-metal kernel targeting x86_64-unknown-none target.
2Boot kernel image in headless QEMU to verify GDT and UART serial initialization.
lab-sandbox — simulated environment
INFINITY LAB SANDBOX v2.6 — simulated shell
Type the command for the current objective. Helpers: "hint", "solution", "clear".
$
OBJECTIVE 1 / 2 — type "hint" if stuck
SYNAPSE VERIFICATION
QUERY 1 // 1
What does the 'x86-interrupt' calling convention ensure when compiling interrupt handlers in Rust?
It automatically saves and restores all scratch registers and handles stack realignment before executing the 'iretq' instruction
It converts the CPU from 64-bit long mode back to 16-bit real mode
It allocates an emergency heap buffer for panic backtraces
It sends an ACPI shutdown signal to the motherboard