m³OS docs GitHub

Phase 01

Boot Foundation

Boot the kernel through UEFI, print useful output over serial, and halt cleanly. This is the first end-to-end proof that the workspace, toolchain, boot path, and panic path all work together.

Complete

Learning goal

Understand `#![no_std]` and `#![no_main]`.

Category

foundations

Builds on

Why this phase matters

Boot the kernel through UEFI, print useful output over serial, and halt cleanly. This is the first end-to-end proof that the workspace, toolchain, boot path, and panic path all work together.

How it works in m3OS

The boot path has one job: get from a host-side Cargo command to running Rust code in a no_std kernel with enough early diagnostics to understand what happened. In m³OS, that means:

How it builds on earlier phases

This phase establishes the first teachable slice of the system and becomes the baseline for everything that follows.

Implementation outline

  • Set up the kernel crate and host-side xtask.
  • Define the target and runner configuration used for OS builds.
  • Initialize COM1 serial and expose simple print macros.
  • Install a logger backend that writes through serial.
  • Add a minimal kernel_main entry point and hlt loop.
  • Add a panic handler that emits enough context to debug early failures.

Task progress snapshot

20 of 20 tracked tasks are complete.

Documentation targets

  • Documentation deliverables have not been listed yet.

Deferred follow-on work

  • framebuffer output
  • test harness integration beyond basic smoke testing
  • real hardware boot support beyond the documented QEMU path

Source materials

Important code

Code spotlight cards

Code spotlight

Implement a minimal kernel_main entry point

kernel/src/main.rs L8-L24

Implement a minimal kernel_main entry point. Why it matters: This is the first code that runs after the bootloader hands off control; it must reach a stable halt loop. Focus on `kernel_main` and `entry_point!(kernel_main)` in `kernel/src/main.rs` while you trace the snippet.

entry_point!(kernel_main);

fn kernel_main(_boot_info: &'static mut BootInfo) -> ! {
    serial::init();
    serial::init_logger();

    serial_println!("[ostest] Hello from kernel!");
    log::info!("Kernel initialized");

    hlt_loop();
}

fn hlt_loop() -> ! {
    loop {
        x86_64::instructions::hlt();
    }
}

Code spotlight

Add serial initialization and print macros

kernel/src/serial.rs L8-L12

Add serial initialization and print macros. Why it matters: Serial output is the primary debug channel in headless QEMU; without it there is no visibility into boot progress. Focus on `init` and `serial_print!` in `kernel/src/serial.rs` while you trace the snippet.

pub fn init() {
    let mut serial_port = unsafe { SerialPort::new(COM1_PORT) };
    serial_port.init();
    *SERIAL1.lock() = Some(serial_port);
}

Code spotlight

Implement cargo xtask image

xtask/src/main.rs See file

Implement cargo xtask image. Why it matters: Produces a bootable disk image that QEMU (or real hardware) can load via UEFI. Focus on `xtask/src/main.rs` while you trace the snippet.

Key files

  • xtask/src/main.rs — The host-side logic lives in xtask/src/main.rs.
  • kernel/src/main.rs — The kernel entry point lives in kernel/src/main.rs.
  • kernel/src/serial.rs — The serial implementation in kernel/src/serial.rs provides:

How real OSes differ

  • Production kernels usually support many boot environments, richer hardware discovery, multiple log sinks, and more defensive boot diagnostics. A learning project can keep the boot path narrow and explicit so the reader can see every step without being buried in platform variation.

Success criteria

  • The kernel boots in QEMU through UEFI.
  • Serial output includes a clear startup message.
  • Panics print a message and halt instead of silently freezing.
  • Image generation is predictable and reproducible.

Related phases

Keep exploring the roadmap