deb-bootc-image-builder/docs/bootloader.md
robojerk d2d4c2e4e7
Some checks failed
particle-os CI / Test particle-os (push) Failing after 1s
particle-os CI / Integration Test (push) Has been skipped
particle-os CI / Security & Quality (push) Failing after 1s
Test particle-os Basic Functionality / test-basic (push) Failing after 1s
Tests / test (1.21.x) (push) Failing after 2s
Tests / test (1.22.x) (push) Failing after 1s
particle-os CI / Build and Release (push) Has been skipped
Major refactor: Remove debos integration, add particle-os CLI system, implement OSTree stages, and create comprehensive build pipeline
2025-08-12 16:17:39 -07:00

18 KiB

Bootloader Implementation Guide

Overview

This document provides comprehensive guidance on implementing bootloaders in the deb-bootc-image-builder project. It covers the integration of traditional GRUB bootloaders with modern bootupd management, drawing from both debos and osbuild methodologies.

Table of Contents

  1. Bootloader Fundamentals
  2. Integration Approaches
  3. debos Methodology
  4. osbuild Integration
  5. Hybrid Implementation Strategy
  6. Technical Implementation
  7. Testing and Validation
  8. Troubleshooting
  9. Future Considerations

Bootloader Fundamentals

What is a Bootloader?

A bootloader is the first software program that runs when a computer starts up. It's responsible for:

  • Loading the operating system kernel
  • Providing boot configuration options
  • Handling different boot modes (UEFI vs BIOS)
  • Managing boot parameters and kernel command lines

Types of Bootloaders

1. Traditional GRUB2

  • Purpose: Classic bootloader for Linux systems
  • Features: Menu-based boot selection, kernel parameter editing
  • Limitations: Manual updates, distribution-specific configurations
  • Use Case: Standard Linux installations, legacy systems

2. Modern bootupd

  • Purpose: Distribution-independent bootloader updater
  • Features: Automatic updates, UEFI/BIOS compatibility, OSTree support
  • Advantages: Cross-distribution, automated management
  • Use Case: Container-based systems, modern Linux distributions

Boot Process Flow

Firmware (UEFI/BIOS) → Bootloader → Kernel → Init System → User Space
     ↓                    ↓         ↓         ↓           ↓
  Hardware           GRUB/bootupd  Linux   systemd     Applications
  Detection          Selection     Load    Startup     Execution

Integration Approaches

1. Pure debos Approach

Philosophy: "Build from scratch" with full control Method: Manual bootloader installation via run actions Advantages: Complete control, customizable, distribution-agnostic Disadvantages: Complex, error-prone, requires extensive scripting

2. Pure osbuild Approach

Philosophy: "Declarative pipeline" with structured stages Method: Dedicated bootloader stages (org.osbuild.grub2, org.osbuild.bootupd) Advantages: Structured, reliable, well-tested Disadvantages: Less flexible, Red Hat/Fedora centric

Philosophy: "Best of both worlds" - debos flexibility with osbuild patterns Method: debos run actions implementing osbuild-style bootloader management Advantages: Flexible, reliable, modern, distribution-independent Disadvantages: Requires careful implementation, testing overhead

debos Methodology

Core Principles

debos doesn't have built-in bootloader support, but provides the infrastructure to implement it:

# debos recipe structure for bootloader integration
actions:
  - action: debootstrap
    # Create base system
  
  - action: apt
    # Install bootloader packages
  
  - action: run
    chroot: true
    script: install-bootloader.sh
  
  - action: run
    chroot: true
    script: configure-bootloader.sh

Key Components

1. Package Installation

# install-bootloader.sh
apt-get update
apt-get install -y grub-efi-amd64 efibootmgr bootupd

2. GRUB Configuration

# configure-grub.sh
grub-install --target=x86_64-efi --efi-directory=/boot/efi --boot-directory=/boot /dev/sda
update-grub

3. bootupd Integration

# run-bootupd.sh
bootupctl backend install --device=/dev/sda

Advantages of debos Approach

  • Full Control: Complete customization of bootloader setup
  • Distribution Independence: Works with any Debian-based system
  • Flexibility: Can implement complex boot scenarios
  • Debugging: Easy to troubleshoot and modify

Limitations

  • Complexity: Requires extensive shell scripting
  • Error Handling: Manual error checking and recovery
  • Maintenance: Scripts need ongoing maintenance
  • Testing: Each change requires full pipeline testing

osbuild Integration

Architecture Overview

osbuild uses a stage-based pipeline with dedicated bootloader stages:

{
  "type": "org.osbuild.grub2",
  "options": {
    "root_fs_uuid": "6e4ff95f-f662-45ee-a82a-bdf44a2d0b75",
    "boot_fs_uuid": "0194fdc2-fa2f-4cc0-81d3-ff12045b73c8",
    "kernel_opts": "ro no_timer_check console=ttyS0,115200n8",
    "uefi": {
      "vendor": "fedora",
      "unified": true
    }
  }
}

Key Stages

1. GRUB2 Stage (org.osbuild.grub2)

  • Purpose: Install and configure GRUB bootloader
  • Features: UEFI/BIOS support, kernel parameter management
  • Configuration: Declarative options for boot settings

2. bootupd Stage (org.osbuild.bootupd)

  • Purpose: Modern bootloader management and updates
  • Features: Cross-distribution compatibility, automatic updates
  • Integration: Works with existing GRUB installations

Implementation Details

# From osbuild bootupd stage
def main(args, options):
    deployment = options.get("deployment", None)
    static_configs = options.get("static-configs", False)
    bios = options.get("bios", {})
    device = bios.get("device", "")
    
    # Run bootupctl backend install
    cmd = ['chroot', root, '/usr/bin/bootupctl', 'backend', 'install']
    cmd.extend(bootupd_args)
    cmd.append(mounts)
    subprocess.run(cmd, check=True)

Advantages of osbuild Approach

  • Structured: Well-defined stages and options
  • Reliable: Extensive testing and validation
  • Modern: Built-in support for contemporary bootloaders
  • Maintainable: Clear separation of concerns

Limitations

  • Red Hat Centric: Primarily designed for Fedora/RHEL
  • Less Flexible: Limited customization options
  • Dependency: Tied to osbuild ecosystem
  • Complexity: Requires understanding of osbuild internals

Hybrid Implementation Strategy

Design Philosophy

Combine the flexibility of debos with the reliability patterns of osbuild:

  1. Use debos infrastructure for system building and customization
  2. Implement osbuild patterns for bootloader management
  3. Create reusable components that can be shared across recipes
  4. Maintain distribution independence while leveraging proven approaches

Implementation Structure

# Hybrid debos recipe with osbuild patterns
actions:
  - action: debootstrap
    suite: bookworm
    variant: minbase
  
  - action: apt
    packages:
      - grub-efi-amd64
      - efibootmgr
      - bootupd
  
  - action: run
    chroot: true
    script: scripts/bootloader/install-grub.sh
  
  - action: run
    chroot: true
    script: scripts/bootloader/configure-grub.sh
  
  - action: run
    chroot: true
    script: scripts/bootloader/install-bootupd.sh
  
  - action: run
    chroot: true
    script: scripts/bootloader/run-bootupd.sh

Component Organization

scripts/
├── bootloader/
│   ├── install-grub.sh      # GRUB package installation
│   ├── configure-grub.sh    # GRUB configuration and installation
│   ├── install-bootupd.sh   # bootupd installation
│   ├── run-bootupd.sh       # bootupd backend configuration
│   └── common.sh            # Shared functions and variables
├── system/
│   ├── setup-filesystem.sh  # Filesystem preparation
│   └── configure-system.sh  # System configuration
└── validation/
    ├── test-bootloader.sh   # Bootloader validation
    └── test-boot.sh         # Boot testing

Technical Implementation

1. GRUB Installation

Package Requirements

# Essential GRUB packages
grub-efi-amd64      # UEFI GRUB bootloader
efibootmgr          # UEFI boot manager
grub-common         # GRUB configuration files

Installation Process

#!/bin/bash
# install-grub.sh

set -e

echo "Installing GRUB bootloader..."

# Install packages
apt-get update
apt-get install -y grub-efi-amd64 efibootmgr grub-common

# Verify installation
grub-install --version
efibootmgr --version

echo "GRUB installation completed successfully"

2. GRUB Configuration

Basic Configuration

#!/bin/bash
# configure-grub.sh

set -e

echo "Configuring GRUB bootloader..."

# Create GRUB configuration directory
mkdir -p /boot/grub

# Set GRUB defaults
cat > /etc/default/grub << 'EOF'
GRUB_TIMEOUT=5
GRUB_DEFAULT=0
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT=console
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX=""
EOF

# Install GRUB to disk
grub-install --target=x86_64-efi \
    --efi-directory=/boot/efi \
    --boot-directory=/boot \
    /dev/sda

# Generate GRUB configuration
update-grub

echo "GRUB configuration completed successfully"

Advanced Configuration

# Custom kernel parameters
GRUB_CMDLINE_LINUX="console=ttyS0,115200n8 ro no_timer_check"

# UEFI-specific settings
GRUB_CMDLINE_LINUX_UEFI="efi=novamap"

# Boot menu customization
GRUB_THEME="/boot/grub/themes/debian/theme.txt"
GRUB_GFXMODE=1024x768

3. bootupd Integration

Installation

#!/bin/bash
# install-bootupd.sh

set -e

echo "Installing bootupd..."

# Check if bootupd is available
if command -v bootupctl >/dev/null 2>&1; then
    echo "bootupd already installed"
    exit 0
fi

# Try to install from package repositories
if apt-get install -y bootupd; then
    echo "bootupd installed from package repository"
else
    echo "Package installation failed, attempting manual installation"
    
    # Clone and build bootupd
    git clone https://github.com/coreos/bootupd.git /tmp/bootupd
    cd /tmp/bootupd
    
    # Build requirements
    apt-get install -y cargo build-essential
    
    # Build and install
    cargo build --release
    cp target/release/bootupd /usr/bin/
    cp target/release/bootupctl /usr/bin/
    
    # Cleanup
    cd /
    rm -rf /tmp/bootupd
fi

echo "bootupd installation completed"

Configuration

#!/bin/bash
# run-bootupd.sh

set -e

echo "Configuring bootupd backend..."

# Verify bootupd is available
if ! command -v bootupctl >/dev/null 2>&1; then
    echo "ERROR: bootupctl not found"
    exit 1
fi

# Get device information
DEVICE=${1:-/dev/sda}
if [ ! -b "$DEVICE" ]; then
    echo "ERROR: Device $DEVICE not found or not a block device"
    exit 1
fi

# Run bootupd backend install
echo "Installing bootupd backend on $DEVICE..."
bootupctl backend install --device="$DEVICE"

# Verify installation
bootupctl status

echo "bootupd backend configuration completed"

4. Filesystem Preparation

Partition Layout

#!/bin/bash
# setup-filesystem.sh

set -e

echo "Setting up filesystem for bootloader..."

# Create GPT partition table
parted /dev/sda mklabel gpt

# Create EFI system partition (ESP)
parted /dev/sda mkpart primary fat32 1MiB 257MiB
parted /dev/sda set 1 boot on
parted /dev/sda set 1 esp on

# Create root filesystem partition
parted /dev/sda mkpart primary ext4 257MiB 100%

# Format partitions
mkfs.fat -F32 /dev/sda1
mkfs.ext4 /dev/sda2

# Mount partitions
mkdir -p /mnt/boot/efi
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot/efi

echo "Filesystem setup completed"

Mount Points

# /etc/fstab configuration
cat > /mnt/etc/fstab << 'EOF'
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
UUID=<root-uuid> /               ext4    defaults        0       1
UUID=<efi-uuid>  /boot/efi       vfat    umask=0077     0       2
proc            /proc           proc    defaults        0       0
sysfs           /sys            sysfs   defaults        0       0
tmpfs           /tmp            tmpfs   defaults        0       0
EOF

Testing and Validation

1. Bootloader Validation

GRUB Verification

#!/bin/bash
# test-bootloader.sh

set -e

echo "Validating bootloader installation..."

# Check GRUB installation
if [ -f /boot/grub/grub.cfg ]; then
    echo "✅ GRUB configuration file exists"
else
    echo "❌ GRUB configuration file missing"
    exit 1
fi

# Check EFI boot entries
if efibootmgr | grep -q "debian"; then
    echo "✅ EFI boot entry found"
else
    echo "❌ EFI boot entry missing"
    exit 1
fi

# Check bootupd status
if command -v bootupctl >/dev/null 2>&1; then
    if bootupctl status | grep -q "ready"; then
        echo "✅ bootupd backend ready"
    else
        echo "⚠️  bootupd backend not ready"
    fi
fi

echo "Bootloader validation completed"

Boot Testing

#!/bin/bash
# test-boot.sh

set -e

echo "Testing boot process..."

# Create test kernel
mkdir -p /boot
cp /boot/vmlinuz-$(uname -r) /boot/vmlinuz-test
cp /boot/initrd.img-$(uname -r) /boot/initrd-test

# Test GRUB boot
if timeout 30s grub-bios-setup /dev/sda; then
    echo "✅ GRUB boot setup successful"
else
    echo "❌ GRUB boot setup failed"
    exit 1
fi

# Test UEFI boot
if [ -d /sys/firmware/efi ]; then
    if efibootmgr | grep -q "debian"; then
        echo "✅ UEFI boot entry configured"
    else
        echo "❌ UEFI boot entry missing"
        exit 1
    fi
fi

echo "Boot testing completed"

2. QEMU Testing

Basic Boot Test

#!/bin/bash
# qemu-test.sh

set -e

echo "Testing boot in QEMU..."

# Create QCOW2 image
qemu-img convert -f raw -O qcow2 debian-bootable.img debian-bootable.qcow2

# Test UEFI boot
echo "Testing UEFI boot..."
timeout 30s qemu-system-x86_64 \
    -m 2G \
    -drive file=debian-bootable.qcow2,format=qcow2 \
    -bios /usr/share/ovmf/OVMF.fd \
    -nographic \
    -serial mon:stdio

# Test BIOS boot
echo "Testing BIOS boot..."
timeout 30s qemu-system-x86_64 \
    -m 2G \
    -drive file=debian-bootable.qcow2,format=qcow2 \
    -nographic \
    -serial mon:stdio

echo "QEMU testing completed"

Troubleshooting

Common Issues

1. GRUB Installation Failures

Problem: grub-install fails with "EFI variables are not supported" Cause: Running in non-UEFI environment Solution: Use --target=i386-pc for BIOS or ensure UEFI environment

# BIOS installation
grub-install --target=i386-pc /dev/sda

# UEFI installation
grub-install --target=x86_64-efi --efi-directory=/boot/efi --boot-directory=/boot /dev/sda

2. bootupd Backend Failures

Problem: bootupctl backend install fails Cause: Missing device or insufficient permissions Solution: Verify device path and run with appropriate privileges

# Check device
lsblk
fdisk -l

# Run with proper device
bootupctl backend install --device=/dev/sda

3. EFI Boot Entry Issues

Problem: System doesn't boot from EFI Cause: Missing or incorrect EFI boot entry Solution: Manually create EFI boot entry

# Create EFI boot entry
efibootmgr --create --disk /dev/sda --part 1 --loader /EFI/debian/grubx64.efi --label "Debian"

# Verify entry
efibootmgr

Debugging Techniques

1. GRUB Debug Mode

# Enable GRUB debug output
echo 'GRUB_TERMINAL_OUTPUT="console serial"' >> /etc/default/grub
echo 'GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' >> /etc/default/grub

# Regenerate configuration
update-grub

2. bootupd Verbose Mode

# Enable verbose bootupd output
bootupctl --verbose backend install --device=/dev/sda

# Check detailed status
bootupctl --verbose status

3. EFI Debug Information

# Check EFI variables
efibootmgr -v

# Check EFI firmware
dmesg | grep -i efi

# Check mounted EFI partitions
mount | grep efi

Future Considerations

1. Secure Boot Integration

Implementation Strategy

# Install secure boot components
apt-get install -y shim-signed grub-efi-amd64-signed

# Configure secure boot
mokutil --import /etc/ssl/certs/ca-certificates.crt

Key Considerations

  • Certificate Management: Proper CA certificate handling
  • Key Signing: Secure key generation and storage
  • Compatibility: Ensuring bootloader compatibility with secure boot

2. OSTree Integration

bootupd OSTree Support

# OSTree deployment configuration
bootupctl backend install --device=/dev/sda --ostree-deployment=debian:debian/13/x86_64/standard

Benefits

  • Atomic Updates: Rollback capability
  • Consistency: Reproducible deployments
  • Efficiency: Delta updates and compression

3. Multi-Architecture Support

ARM64 Support

# ARM64 GRUB installation
grub-install --target=arm64-efi --efi-directory=/boot/efi --boot-directory=/boot /dev/sda

# ARM64 bootupd
bootupctl backend install --device=/dev/sda --arch=arm64

RISC-V Support

# RISC-V bootloader (when available)
# Currently limited support, requires custom implementation

4. Cloud Integration

Cloud-Init Integration

# Install cloud-init
apt-get install -y cloud-init

# Configure cloud-init for bootloader
cat > /etc/cloud/cloud.cfg.d/99_bootloader.cfg << 'EOF'
bootcmd:
  - bootupctl backend install --device=/dev/sda
EOF

Benefits

  • Automation: Automated bootloader configuration
  • Scalability: Consistent deployment across instances
  • Maintenance: Centralized configuration management

Conclusion

The hybrid approach combining debos flexibility with osbuild patterns provides the best foundation for bootloader implementation in deb-bootc-image-builder. This approach offers:

  1. Distribution Independence: Works across different Debian-based systems
  2. Modern Bootloader Support: Integration with bootupd for contemporary needs
  3. Flexibility: Customizable bootloader configurations
  4. Reliability: Proven patterns from production systems
  5. Maintainability: Clear structure and reusable components

Key Success Factors

  • Thorough Testing: Comprehensive validation of boot processes
  • Error Handling: Robust error checking and recovery
  • Documentation: Clear implementation guides and troubleshooting
  • Community Engagement: Collaboration with debos and bootupd communities

Next Steps

  1. Implement Core Components: Create the basic bootloader installation scripts
  2. Integration Testing: Validate the complete pipeline
  3. Documentation: Expand this guide with specific examples
  4. Community Feedback: Gather input from users and contributors
  5. Continuous Improvement: Iterate based on real-world usage

This bootloader implementation strategy positions deb-bootc-image-builder as a modern, flexible tool for creating bootable container images while maintaining compatibility with existing Linux infrastructure.