Files
zosbuilder/docs/INIT.md

8.0 KiB

Alpine Zero-OS Init Script Design

Design documentation for the Alpine-based init script that maintains the exact same tmpfs approach as the current system.

Current Init Flow Analysis

The existing init script (config/init/init) does:

  1. Mount basic filesystems (proc, sysfs, devtmpfs)
  2. Create 1536M tmpfs at /mnt/root
  3. Copy entire filesystem to tmpfs
  4. Mount filesystems in tmpfs
  5. Hardware detection with udev
  6. Load essential drivers
  7. Debug file injection (if available)
  8. switch_root to tmpfs and exec zinit

Alpine Init Script - configs/init

#!/bin/sh
# Alpine-based Zero-OS Init Script
# Maintains identical flow to original busybox version

echo ""
echo "============================================"
echo "==       ZERO-OS ALPINE INITRAMFS        =="
echo "============================================"

echo "[+] creating ram filesystem"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t tmpfs tmpfs /mnt/root -o size=1536M
mount -t devtmpfs devtmpfs /dev

echo "[+] building ram filesystem"
target="/mnt/root"

# Copy Alpine filesystem to tmpfs (same as original)
echo "  copying /bin..."
cp -ar /bin $target
echo "  copying /etc..."
cp -ar /etc $target
echo "  copying /lib..."
cp -ar /lib* $target
echo "  copying /usr..."
cp -ar /usr $target
echo "  copying /root..."
cp -ar /root $target
echo "  copying /sbin..."
cp -ar /sbin $target
echo "  copying /tmp..."
cp -ar /tmp $target
echo "  copying /var..."
cp -ar /var $target
echo "  copying /run..."
cp -ar /run $target

# Create essential directories
mkdir -p $target/dev
mkdir -p $target/sys
mkdir -p $target/proc
mkdir -p $target/mnt

# Mount filesystems in tmpfs
mount -t proc proc $target/proc
mount -t sysfs sysfs $target/sys
mount -t devtmpfs devtmpfs $target/dev

# Mount devpts for terminals
mkdir -p $target/dev/pts
mount -t devpts devpts $target/dev/pts

echo "[+] setting environment"
export PATH

echo "[+] probing drivers"
# Use Alpine's udev instead of busybox udevadm
if [ -x /sbin/udevd ]; then
    echo "  starting udevd..."
    udevd --daemon
    
    echo "  triggering device discovery..."
    udevadm trigger --action=add --type=subsystems
    udevadm trigger --action=add --type=devices
    udevadm settle
    
    echo "  stopping udevd..."
    kill $(pidof udevd) || true
else
    echo "  warning: udevd not found, skipping hardware detection"
fi

echo "[+] loading essential drivers"
# Load core drivers for storage and network
modprobe btrfs 2>/dev/null || true
modprobe fuse 2>/dev/null || true
modprobe overlay 2>/dev/null || true

# Load storage drivers
modprobe ahci 2>/dev/null || true
modprobe nvme 2>/dev/null || true
modprobe virtio_blk 2>/dev/null || true
modprobe virtio_scsi 2>/dev/null || true

# Load network drivers  
modprobe virtio_net 2>/dev/null || true
modprobe e1000 2>/dev/null || true
modprobe e1000e 2>/dev/null || true

# Unmount init filesystems
umount /proc 2>/dev/null || true
umount /sys 2>/dev/null || true

echo "[+] checking for debug files"
if [ -e /init-debug ]; then
    echo "  executing debug script..."
    sh /init-debug
fi

echo "[+] switching root"
echo "  exec switch_root /mnt/root /sbin/zinit init"
exec switch_root /mnt/root /sbin/zinit init

Debug Script - configs/init-debug

For debug mode compatibility:

#!/bin/sh
# Debug file injection script (Alpine version)
# Maintains compatibility with existing debug workflow

echo "[+] debug mode enabled"

# Check for debug device (same as original)
if [ -b /dev/sda1 ]; then
    echo "  debug device found: /dev/sda1"
    
    # Create temporary mount point
    mkdir -p /mnt/debug
    
    # Try to mount as vfat (same as original)
    if mount -t vfat -o ro /dev/sda1 /mnt/debug 2>/dev/null; then
        echo "  mounted debug device"
        
        # Check for debug marker file
        if [ -f /mnt/debug/.zero-os-debug ]; then
            echo "  debug marker found, copying files..."
            
            # Copy all files from debug device to tmpfs root
            target="/mnt/root"
            if [ -d "$target" ]; then
                cp -rv /mnt/debug/* "$target/" 2>/dev/null || true
                echo "  debug files copied to tmpfs"
            else
                echo "  warning: tmpfs root not ready yet"
            fi
        else
            echo "  no debug marker (.zero-os-debug) found"
        fi
        
        # Unmount debug device
        umount /mnt/debug 2>/dev/null || true
    else
        echo "  failed to mount debug device"
    fi
    
    # Cleanup
    rmdir /mnt/debug 2>/dev/null || true
else
    echo "  no debug device found"
fi

echo "[+] debug initialization complete"

Key Differences from Original

Advantages of Alpine Version:

  1. Better error handling: Uses || true to prevent failures
  2. More verbose output: Better logging for debugging
  3. Alpine tools: Uses Alpine's optimized udev/modprobe
  4. Modular approach: Separates debug script for clarity
  5. Robust driver loading: Loads more essential drivers upfront

Maintained Compatibility:

  1. Identical filesystem structure: Same tmpfs copy approach
  2. Same mount points: Preserves all original mount points
  3. Same debug workflow: Compatible with existing debug injection
  4. Same zinit execution: Identical handoff to zinit
  5. Same memory usage: 1536M tmpfs size preserved

Hardware Detection Improvements

Enhanced Driver Loading:

# Storage drivers (embedded in initramfs)
modprobe ahci          # SATA controllers
modprobe nvme          # NVMe SSDs
modprobe virtio_blk    # Virtual block devices
modprobe virtio_scsi   # Virtual SCSI
modprobe usb_storage   # USB storage

# Network drivers (embedded in initramfs)  
modprobe virtio_net    # Virtual network
modprobe e1000         # Intel Gigabit
modprobe e1000e        # Intel Gigabit Enhanced
modprobe r8169         # Realtek
modprobe tg3           # Broadcom

# Filesystem drivers
modprobe btrfs         # Primary filesystem
modprobe overlay       # Container filesystems
modprobe fuse          # FUSE filesystems

Advanced Hardware Detection:

# Optional: More sophisticated hardware detection
if [ -x /usr/bin/lspci ]; then
    echo "[+] detecting hardware..."
    
    # Load drivers based on detected hardware
    for device in $(lspci -n | awk '{print $3}'); do
        case "$device" in
            "8086:*") # Intel devices
                modprobe e1000e 2>/dev/null || true
                ;;
            "10ec:*") # Realtek devices  
                modprobe r8169 2>/dev/null || true
                ;;
            "14e4:*") # Broadcom devices
                modprobe tg3 2>/dev/null || true
                ;;
        esac
    done
fi

Error Handling and Logging

Robust Error Handling:

# Function for safe command execution
safe_exec() {
    local cmd="$1"
    local desc="$2"
    
    echo "  $desc..."
    if $cmd; then
        echo "    success"
    else
        echo "    warning: $desc failed (continuing)"
    fi
}

# Usage examples:
safe_exec "modprobe btrfs" "loading btrfs driver"
safe_exec "udevadm settle" "waiting for device settlement"

Enhanced Logging:

# Optional: Detailed logging for debug builds
if [ "$BUILDMODE" = "debug" ]; then
    # Log to both console and file
    exec 1> >(tee -a /mnt/root/var/log/init.log)
    exec 2> >(tee -a /mnt/root/var/log/init.log >&2)
    
    echo "[DEBUG] Init script started at $(date)"
    echo "[DEBUG] Available memory: $(free -m)"
    echo "[DEBUG] Detected hardware: $(lspci -nn)"
fi

Integration with Zinit

Zinit Configuration Preservation:

  • All existing zinit YAML configs copied unchanged
  • Service dependencies maintained
  • Init scripts preserved in /etc/zinit/init/
  • Same service execution flow

Zinit Execution Environment:

# Ensure clean environment for zinit
export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
export HOME="/root"
export TERM="linux"

# Clear any init-specific variables
unset target

# Execute zinit with same arguments
exec switch_root /mnt/root /sbin/zinit init

This design maintains 100% compatibility with the existing system while leveraging Alpine's more robust and modern tooling.