- make-uefi-iso.sh: UEFI ISO image builder - test_boot.S, test_boot.ld: test boot assembly and linker script - eim_config.toml: EIM (External Interface Module) configuration - edk2-ovmf RPM for UEFI firmware - GAP_ANALYSIS_PIKEOS_PARITY.md: PikeOS parity gap analysis
218 lines
6.7 KiB
Bash
Executable file
218 lines
6.7 KiB
Bash
Executable file
#!/bin/bash
|
|
# UniversalisOS Disk Image Builder
|
|
# Creates a bootable GPT disk image with UniversalisOS + guest OS images
|
|
# Usage: ./scripts/build_disk_image.sh [--size 32G] [--output universalisos.img]
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
KERNEL_DIR="$(dirname "$SCRIPT_DIR")"
|
|
GUESTS_DIR="${GUESTS_DIR:-/home/fabiorafaelcoutada/portugalfuturista/guests}"
|
|
OUTPUT="${OUTPUT:-${KERNEL_DIR}/universalisos.img}"
|
|
SIZE="${SIZE:-32G}"
|
|
MNT="/tmp/uos_disk_mount"
|
|
ESP_MNT="${MNT}/esp"
|
|
DATA_MNT="${MNT}/data"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${GREEN}[UOS]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
err() { echo -e "${RED}[ERR]${NC} $*" >&2; exit 1; }
|
|
|
|
# Parse args
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--size) SIZE="$2"; shift 2;;
|
|
--output) OUTPUT="$2"; shift 2;;
|
|
--guests) GUESTS_DIR="$2"; shift 2;;
|
|
--help) echo "Usage: $0 [--size 32G] [--output universalisos.img] [--guests /path/to/guests]"; exit 0;;
|
|
*) err "Unknown option: $1";;
|
|
esac
|
|
done
|
|
|
|
# Check dependencies
|
|
for cmd in parted mkfs.fat mkfs.ext4 grub2-install mtools; do
|
|
command -v "$cmd" &>/dev/null || err "Missing: $cmd (install with: sudo dnf install $cmd)"
|
|
done
|
|
|
|
log "Building UniversalisOS disk image: ${OUTPUT} (${SIZE})"
|
|
|
|
# ============================================================
|
|
# Step 1: Create raw disk image
|
|
# ============================================================
|
|
log "Creating ${SIZE} disk image..."
|
|
dd if=/dev/zero of="$OUTPUT" bs=1 count=0 seek="$SIZE" 2>/dev/null
|
|
|
|
# ============================================================
|
|
# Step 2: Create GPT partition table
|
|
# ============================================================
|
|
log "Creating GPT partition table..."
|
|
parted -s "$OUTPUT" mklabel gpt
|
|
parted -s "$OUTPUT" mkpart ESP fat32 1MiB 513MiB
|
|
parted -s "$OUTPUT" set 1 esp on
|
|
parted -s "$OUTPUT" mkpart primary ext4 513MiB 100%
|
|
|
|
# ============================================================
|
|
# Step 3: Format partitions via loopback
|
|
# ============================================================
|
|
log "Setting up loopback device..."
|
|
LOOP=$(sudo losetup --find --show --partscan "$OUTPUT")
|
|
log "Loopback: ${LOOP}"
|
|
|
|
log "Formatting EFI System Partition (FAT32, 512MB)..."
|
|
sudo mkfs.fat -F 32 "${LOOP}p1"
|
|
|
|
log "Formatting Guest Data Partition (ext4)..."
|
|
sudo mkfs.ext4 -F -L uos-guests "${LOOP}p2"
|
|
|
|
# ============================================================
|
|
# Step 4: Mount and populate
|
|
# ============================================================
|
|
sudo mkdir -p "$ESP_MNT" "$DATA_MNT"
|
|
sudo mount "${LOOP}p1" "$ESP_MNT"
|
|
sudo mount "${LOOP}p2" "$DATA_MNT"
|
|
|
|
# --- EFI System Partition ---
|
|
log "Installing GRUB2 UEFI bootloader..."
|
|
sudo mkdir -p "$ESP_MNT/EFI/BOOT"
|
|
sudo mkdir -p "$ESP_MNT/boot/grub"
|
|
|
|
# Copy kernel
|
|
log "Copying kernel..."
|
|
sudo cp "${KERNEL_DIR}/build/x86_64/qemu-x86_64-virt/universalisos.elf" "$ESP_MNT/boot/"
|
|
|
|
# Copy OVMF firmware
|
|
log "Copying OVMF firmware..."
|
|
sudo cp /usr/share/OVMF/OVMF_CODE.fd "$ESP_MNT/boot/ovmf.fd"
|
|
|
|
# Create GRUB config
|
|
log "Creating GRUB configuration..."
|
|
sudo tee "$ESP_MNT/boot/grub/grub.cfg" > /dev/null << 'GRUB_CFG'
|
|
set timeout=10
|
|
set default=0
|
|
|
|
# Load GRUB modules
|
|
insmod part_gpt
|
|
insmod fat
|
|
insmod ext2
|
|
insmod normal
|
|
insmod menuentry
|
|
|
|
menuentry "UniversalisOS — Android TV STB (IPTV)" {
|
|
multiboot /boot/universalisos.elf guest=android-stb
|
|
module /boot/ovmf.fd ovmf
|
|
boot
|
|
}
|
|
|
|
menuentry "UniversalisOS — Windows 10 Pro" {
|
|
multiboot /boot/universalisos.elf guest=windows-10
|
|
module /boot/ovmf.fd ovmf
|
|
boot
|
|
}
|
|
|
|
menuentry "UniversalisOS — Linux (Debian)" {
|
|
multiboot /boot/universalisos.elf guest=linux
|
|
module /boot/ovmf.fd ovmf
|
|
boot
|
|
}
|
|
|
|
menuentry "UniversalisOS — Safe Mode (no guests)" {
|
|
multiboot /boot/universalisos.elf safe
|
|
boot
|
|
}
|
|
|
|
menuentry "UniversalisOS — UEFI Shell" {
|
|
multiboot /boot/universalisos.elf uefi-shell
|
|
boot
|
|
}
|
|
GRUB_CFG
|
|
|
|
# Install GRUB EFI binary
|
|
log "Installing GRUB EFI binary..."
|
|
sudo grub2-install \
|
|
--target=x86_64-efi \
|
|
--efi-directory="$ESP_MNT" \
|
|
--boot-directory="$ESP_MNT/boot" \
|
|
--removable \
|
|
"$LOOP" 2>/dev/null || warn "grub2-install may need --no-nvram on some systems"
|
|
|
|
# --- Guest Data Partition ---
|
|
log "Copying guest OS images..."
|
|
|
|
# Copy Windows 10 ISO
|
|
if [ -f "$GUESTS_DIR/Windows10Pro.iso" ]; then
|
|
log " → Windows 10 Pro ($(du -h "$GUESTS_DIR/Windows10Pro.iso" | cut -f1))"
|
|
sudo cp "$GUESTS_DIR/Windows10Pro.iso" "$DATA_MNT/windows10.iso"
|
|
fi
|
|
|
|
# Create guest configuration file
|
|
log "Creating guest configuration..."
|
|
sudo tee "$DATA_MNT/guests.cfg" > /dev/null << 'GUESTS_CFG'
|
|
# UniversalisOS Guest Configuration
|
|
# Format: name|type|disk_image|ram_mb|vcpus|firmware
|
|
#
|
|
# type: windows, linux, android-stb, embedded
|
|
# firmware: uefi, bios, baremetal
|
|
|
|
# Android TV STB — ISP IPTV
|
|
android-stb|android-stb|android-stb.img|2048|2|uefi
|
|
|
|
# Windows 10 Pro
|
|
windows-10|windows|windows10.iso|4096|2|uefi
|
|
|
|
# Linux Debian
|
|
linux|linux|linux.img|2048|1|uefi
|
|
GUESTS_CFG
|
|
|
|
# Create placeholder Android STB disk image (1GB sparse)
|
|
log "Creating Android STB placeholder image..."
|
|
sudo dd if=/dev/zero of="$DATA_MNT/android-stb.img" bs=1 count=0 seek=1G 2>/dev/null
|
|
|
|
# Create placeholder Linux disk image (2GB sparse)
|
|
log "Creating Linux placeholder image..."
|
|
sudo dd if=/dev/zero of="$DATA_MNT/linux.img" bs=1 count=0 seek=2G 2>/dev/null
|
|
|
|
# ============================================================
|
|
# Step 5: Install GRUB to MBR (for BIOS fallback)
|
|
# ============================================================
|
|
log "Installing BIOS fallback GRUB..."
|
|
sudo mkdir -p "$ESP_MNT/boot/grub/i386-pc"
|
|
sudo grub2-install \
|
|
--target=i386-pc \
|
|
--boot-directory="$ESP_MNT/boot" \
|
|
"$LOOP" 2>/dev/null || warn "BIOS GRUB install skipped (UEFI-only is fine)"
|
|
|
|
# ============================================================
|
|
# Step 6: Cleanup
|
|
# ============================================================
|
|
log "Unmounting..."
|
|
sudo umount "$ESP_MNT"
|
|
sudo umount "$DATA_MNT"
|
|
sudo losetup -d "$LOOP"
|
|
sudo rmdir "$ESP_MNT" "$DATA_MNT" "$MNT" 2>/dev/null || true
|
|
|
|
# ============================================================
|
|
# Step 7: Convert to USB-flashable format
|
|
# ============================================================
|
|
log "Disk image ready: ${OUTPUT}"
|
|
log "Size: $(du -h "$OUTPUT" | cut -f1)"
|
|
log ""
|
|
log "=== Flash to USB ==="
|
|
log " sudo dd if=${OUTPUT} of=/dev/sdX bs=4M status=progress conv=fsync"
|
|
log ""
|
|
log "=== Flash to NVMe SSD ==="
|
|
log " sudo dd if=${OUTPUT} of=/dev/nvme0n1 bs=4M status=progress conv=fsync"
|
|
log ""
|
|
log "=== Test in QEMU ==="
|
|
log " qemu-system-x86_64 \\"
|
|
log " -drive file=${OUTPUT},format=raw,if=none,id=disk \\"
|
|
log " -device nvme,serial=12345,drive=disk \\"
|
|
log " -bios /usr/share/OVMF/OVMF_CODE.fd \\"
|
|
log " -m 8192 -smp 2 -serial stdio -display none"
|
|
log ""
|
|
log "Done!"
|