Files
MetalOS/docs/QEMU_TESTING.md
2025-12-28 18:32:04 +00:00

9.2 KiB

QEMU UEFI Testing Guide

This guide covers testing MetalOS in QEMU with UEFI firmware (OVMF).

Overview

MetalOS uses QEMU with OVMF (Open Virtual Machine Firmware) to test UEFI boot functionality without requiring physical hardware. This enables rapid development and testing of the bootloader and kernel.

Prerequisites

Required Software

  1. QEMU (version 6.0 or later recommended)

    • Provides x86_64 virtualization
    • Supports UEFI firmware
  2. OVMF (UEFI firmware for QEMU)

    • Open-source UEFI implementation
    • Required for UEFI boot in QEMU
  3. mtools (for disk image creation)

    • Creates FAT32 filesystems
    • Manipulates MS-DOS filesystems

Installation

Ubuntu/Debian:

sudo apt-get update
sudo apt-get install qemu-system-x86 ovmf mtools xorriso

Arch Linux:

sudo pacman -S qemu-full edk2-ovmf mtools xorriso

Fedora:

sudo dnf install qemu-system-x86 edk2-ovmf mtools xorriso

macOS:

brew install qemu mtools xorriso
# Note: OVMF may need manual installation

Quick Start

Basic QEMU Boot

# Build and boot MetalOS in QEMU
make qemu

This command:

  1. Builds the bootloader and kernel (or uses placeholders)
  2. Creates a FAT32 disk image with UEFI boot structure
  3. Launches QEMU with OVMF firmware
  4. Boots the system in headless mode

Expected Output:

Building bootloader...
Building kernel...
Creating bootable image...
Using mtools to create FAT32 disk image...
Success! Created build/metalos.img
Starting QEMU with UEFI firmware...
Using OVMF firmware: /usr/share/ovmf/OVMF.fd
Display mode: none (set QEMU_DISPLAY=gtk for graphical)
[UEFI boot messages...]

Verify UEFI Setup

To verify that QEMU and OVMF are properly installed:

make qemu-uefi-test

This boots directly to the UEFI shell without any OS image, confirming your setup works.

Display Modes

MetalOS supports multiple display modes for different use cases:

Headless Mode (Default)

make qemu
# or explicitly
make qemu QEMU_DISPLAY=none

Use cases:

  • CI/CD pipelines
  • Headless servers
  • Automated testing
  • Serial console debugging

Characteristics:

  • No graphical window
  • Serial output only
  • Works in any environment

Graphical Mode - GTK

make qemu QEMU_DISPLAY=gtk

Use cases:

  • Interactive development
  • Visual debugging
  • UI testing

Characteristics:

  • Native GTK window
  • Full graphics support
  • Requires X11/Wayland

Graphical Mode - SDL

make qemu QEMU_DISPLAY=sdl

Use cases:

  • Cross-platform development
  • Alternative to GTK

Characteristics:

  • SDL window
  • Good compatibility
  • Lighter than GTK

Text Mode - Curses

make qemu QEMU_DISPLAY=curses

Use cases:

  • SSH sessions
  • Text-only environments

Characteristics:

  • Terminal-based UI
  • No X11 required
  • Works over SSH

Advanced Testing

Debug Mode

Boot with CPU interrupt and reset debugging:

make qemu-debug

Additional debug output includes:

  • CPU interrupts
  • CPU resets
  • Exception handling
  • Hardware events

GDB Debugging

Debug the kernel with GDB:

Terminal 1 - Start QEMU with GDB server:

make qemu-gdb

QEMU will wait for GDB connection on localhost:1234.

Terminal 2 - Connect GDB:

gdb kernel/metalos.bin
(gdb) target remote localhost:1234
(gdb) break kernel_main
(gdb) continue

Useful GDB commands:

# Set breakpoints
break *0x100000          # Break at address
break kernel_main        # Break at function

# Examine memory
x/10i $rip              # Disassemble 10 instructions
x/10x 0x100000          # Show 10 hex values

# Step through code
stepi                   # Step one instruction
nexti                   # Step over calls
continue                # Continue execution

# Register inspection
info registers          # Show all registers
print $rax              # Print specific register

Disk Image Details

Image Structure

The build/metalos.img file contains:

metalos.img (64 MB FAT32 disk)
├── EFI/
│   └── BOOT/
│       └── bootx64.efi    # UEFI bootloader
└── metalos.bin             # Kernel binary

Inspecting the Image

View the disk image contents:

# List files in the image
mdir -i build/metalos.img ::/

# List EFI boot directory
mdir -i build/metalos.img ::/EFI/BOOT/

# Extract a file
mcopy -i build/metalos.img ::/metalos.bin extracted_kernel.bin

# Get image info
file build/metalos.img

Manual Image Creation

If you need to manually create or modify the image:

# Create empty 64MB image
dd if=/dev/zero of=disk.img bs=1M count=64

# Format as FAT32
mformat -i disk.img -F -v "METALOS" ::

# Create directory structure
mmd -i disk.img ::/EFI
mmd -i disk.img ::/EFI/BOOT

# Copy files
mcopy -i disk.img bootloader/bootx64.efi ::/EFI/BOOT/
mcopy -i disk.img kernel/metalos.bin ::/

OVMF Firmware

Firmware Locations

The Makefile automatically detects OVMF firmware in these locations:

  • /usr/share/OVMF/OVMF_CODE.fd (Ubuntu/Debian)
  • /usr/share/ovmf/OVMF.fd (Ubuntu/Debian alternative)
  • /usr/share/edk2-ovmf/x64/OVMF_CODE.fd (Arch Linux)
  • /usr/share/qemu/ovmf-x86_64.bin (Other systems)

Firmware Variants

OVMF_CODE.fd: Code-only firmware (read-only)

  • Used with -drive if=pflash,readonly=on
  • Best for testing
  • Variables stored separately

OVMF.fd: Combined code and variables

  • Single file for firmware
  • Simpler setup
  • Variables reset on each boot

OVMF.secboot.fd: Secure Boot enabled

  • For secure boot testing
  • Requires signed bootloader

Troubleshooting

QEMU Won't Start

Issue: gtk initialization failed or Could not initialize SDL

Solution: Use headless mode:

make qemu QEMU_DISPLAY=none

OVMF Not Found

Issue: Error: OVMF UEFI firmware not found!

Solution: Install OVMF package:

# Ubuntu/Debian
sudo apt-get install ovmf

# Arch Linux
sudo pacman -S edk2-ovmf

Image Creation Fails

Issue: mformat: command not found

Solution: Install mtools:

# Ubuntu/Debian
sudo apt-get install mtools

# Arch Linux
sudo pacman -S mtools

Boots to UEFI Shell

Expected Behavior: During development, booting to UEFI shell is normal until the bootloader is complete.

What it means:

  • QEMU and OVMF working correctly
  • Disk image recognized (shows as FS0)
  • ⚠️ Bootloader not yet functional (expected in Phase 1)

Next steps: Implement Phase 2 (UEFI Bootloader)

Serial Output Missing

Issue: No serial console output

Solution: Ensure serial port is configured correctly:

  • Output goes to stdio by default
  • Check that -serial stdio is in QEMU command
  • Verify kernel writes to serial port

QEMU Hangs

Issue: QEMU appears to hang during boot

Possible causes:

  1. Bootloader infinite loop
  2. Waiting for input
  3. Hardware initialization issue

Debug steps:

# Use debug mode
make qemu-debug

# Use GDB to inspect state
make qemu-gdb
# In another terminal: gdb kernel/metalos.bin

CI/CD Integration

GitHub Actions

Example workflow for QEMU testing:

name: QEMU Boot Test

on: [push, pull_request]

jobs:
  qemu-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y qemu-system-x86 ovmf mtools
      
      - name: Build and test in QEMU
        run: |
          make qemu QEMU_DISPLAY=none &
          QEMU_PID=$!
          sleep 10
          kill $QEMU_PID || true

Docker Testing

Run QEMU tests in Docker:

FROM ubuntu:latest

RUN apt-get update && apt-get install -y \
    build-essential nasm qemu-system-x86 ovmf mtools

WORKDIR /metalos
COPY . .

CMD ["make", "qemu", "QEMU_DISPLAY=none"]

Performance Tuning

Memory Allocation

Default: 512 MB

Adjust memory:

# Edit Makefile QEMU command
qemu-system-x86_64 ... -m 1024M  # Use 1GB

CPU Configuration

Use multiple cores:

qemu-system-x86_64 ... -smp 2  # 2 cores

KVM Acceleration

Enable KVM for faster emulation (Linux only):

qemu-system-x86_64 ... -enable-kvm

Note: Requires KVM kernel module and permissions.

Best Practices

  1. Always test in headless mode first - Ensures CI/CD compatibility
  2. Use serial output for debugging - More reliable than graphics
  3. Keep disk images small - 64 MB is sufficient for development
  4. Test with different OVMF versions - Ensures compatibility
  5. Document boot behavior changes - Track progress in commits
  6. Use GDB for serious debugging - More powerful than printf
  7. Test on multiple systems - Catch compatibility issues early

Resources