#!/bin/bash set -euo pipefail # Particle-OS Boot Test Script # This script creates a bootable disk image and tests it with QEMU SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" BUILD_DIR="$PROJECT_ROOT/build" TEST_DIR="$PROJECT_ROOT/test" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check prerequisites check_prerequisites() { log_info "Checking prerequisites..." local missing_tools=() for tool in podman qemu-system-x86_64 truncate; do if ! command -v "$tool" >/dev/null 2>&1; then missing_tools+=("$tool") fi done # Check for system tools in /usr/sbin for tool in parted grub-install partprobe; do if [ ! -x "/usr/sbin/$tool" ]; then missing_tools+=("$tool") fi done if [ ${#missing_tools[@]} -gt 0 ]; then log_error "Missing required tools: ${missing_tools[*]}" exit 1 fi # Check if Phase 2 image exists if ! podman image exists particle-os:phase2; then log_error "Phase 2 image not found. Run 'just build-phase2' first." exit 1 fi log_success "All prerequisites satisfied" } # Create test directories setup_test_environment() { log_info "Setting up test environment..." mkdir -p "$BUILD_DIR" "$TEST_DIR" log_success "Test environment ready" } # Create bootable disk image create_bootable_image() { local image_size="2G" local image_path="$TEST_DIR/particle-os-test.img" log_info "Creating bootable disk image ($image_size)..." # Create raw disk image truncate -s "$image_size" "$image_path" # Partition the disk echo "yes" | /usr/sbin/parted "$image_path" mklabel gpt /usr/sbin/parted "$image_path" mkpart primary fat32 1MiB 512MiB /usr/sbin/parted "$image_path" mkpart primary ext4 512MiB 100% /usr/sbin/parted "$image_path" set 1 boot on /usr/sbin/parted "$image_path" set 1 esp on log_success "Disk image created: $image_path" echo "$image_path" } # Mount and prepare the image prepare_image() { local image_path="$1" log_info "Preparing bootable image..." # Create loop device log_info "Creating loop device for: $image_path" local loop_dev=$(sudo losetup --find --show "$image_path") if [ -z "$loop_dev" ]; then log_error "Failed to create loop device" exit 1 fi log_info "Using loop device: $loop_dev" # Debug: show what devices exist log_info "Available loop devices:" ls -la /dev/loop* 2>/dev/null || echo "No loop devices found" # Wait a moment for device nodes to appear sleep 1 # Verify partition devices exist if [ ! -b "${loop_dev}p1" ] || [ ! -b "${loop_dev}p2" ]; then log_error "Partition devices not found. Creating them manually..." sudo partprobe "$loop_dev" sleep 2 # Check again if [ ! -b "${loop_dev}p1" ] || [ ! -b "${loop_dev}p2" ]; then log_error "Partition devices still not found after partprobe" sudo losetup -d "$loop_dev" 2>/dev/null || true exit 1 fi fi # Create filesystems sudo mkfs.fat -F32 "${loop_dev}p1" sudo mkfs.ext4 "${loop_dev}p2" # Mount partitions local mount_root="$TEST_DIR/mount" local mount_boot="$mount_root/boot" local mount_rootfs="$mount_root/rootfs" mkdir -p "$mount_boot" "$mount_rootfs" sudo mount "${loop_dev}p1" "$mount_boot" sudo mount "${loop_dev}p2" "$mount_rootfs" # Extract Phase 2 container to rootfs log_info "Extracting Phase 2 container..." podman create --name temp-phase2 particle-os:phase2 podman export temp-phase2 | sudo tar -x -C "$mount_rootfs" podman rm temp-phase2 # Set up bootloader log_info "Setting up bootloader..." sudo /usr/sbin/grub-install --target=x86_64-efi --efi-directory="$mount_boot" --boot-directory="$mount_boot" --removable "$loop_dev" # Create GRUB config sudo tee "$mount_boot/grub/grub.cfg" > /dev/null <