feat(isobuild): add multi-architecture build and Raspberry Pi support in installer and build tooling

This commit is contained in:
2026-01-13 07:55:09 +00:00
parent 2d4846cfed
commit 2c5ea744f1
13 changed files with 1227 additions and 350 deletions

View File

@@ -1,7 +1,8 @@
#!/bin/bash
#
# EcoOS Installer
# Installs EcoOS from live USB to disk
# Installs EcoOS from live USB/SD to disk
# Supports: x86_64 (UEFI), ARM64 (UEFI), Raspberry Pi (native boot)
#
set -e
@@ -12,6 +13,45 @@ HOSTNAME="ecoos"
USERNAME="ecouser"
SQUASHFS_PATH="/run/live/medium/live/filesystem.squashfs"
# Detect architecture
detect_architecture() {
local arch=$(uname -m)
local is_rpi="no"
# Check if running on Raspberry Pi
if [ -f /sys/firmware/devicetree/base/model ]; then
local model=$(cat /sys/firmware/devicetree/base/model 2>/dev/null || echo "")
if [[ "$model" == *"Raspberry Pi"* ]]; then
is_rpi="yes"
fi
fi
case "$arch" in
x86_64)
ARCH_TYPE="amd64"
BOOT_TYPE="uefi"
;;
aarch64)
if [ "$is_rpi" = "yes" ]; then
ARCH_TYPE="rpi"
BOOT_TYPE="rpi"
else
ARCH_TYPE="arm64"
BOOT_TYPE="uefi"
fi
;;
*)
ARCH_TYPE="unknown"
BOOT_TYPE="unknown"
;;
esac
export ARCH_TYPE BOOT_TYPE
}
# Call architecture detection early
detect_architecture
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
@@ -191,43 +231,66 @@ select_disk() {
partition_disk() {
local disk=$1
log "Partitioning $disk..."
log "Partitioning $disk for $ARCH_TYPE ($BOOT_TYPE boot)..."
# Wipe existing partition table
wipefs -a "$disk" >/dev/null 2>&1 || true
# Create GPT partition table
parted -s "$disk" mklabel gpt
if [ "$BOOT_TYPE" = "rpi" ]; then
# Raspberry Pi uses MBR partition table
log "Creating MBR partition table for Raspberry Pi..."
parted -s "$disk" mklabel msdos
# Create EFI partition (512MB)
parted -s "$disk" mkpart ESP fat32 1MiB 513MiB
parted -s "$disk" set 1 esp on
# Create boot partition (FAT32, 256MB)
parted -s "$disk" mkpart primary fat32 1MiB 257MiB
parted -s "$disk" set 1 boot on
# Create root partition (rest of disk)
parted -s "$disk" mkpart root ext4 513MiB 100%
# Create root partition (rest of disk)
parted -s "$disk" mkpart primary ext4 257MiB 100%
else
# x86_64 and generic ARM64 use GPT with EFI
log "Creating GPT partition table with EFI..."
parted -s "$disk" mklabel gpt
# Create EFI partition (512MB)
parted -s "$disk" mkpart ESP fat32 1MiB 513MiB
parted -s "$disk" set 1 esp on
# Create root partition (rest of disk)
parted -s "$disk" mkpart root ext4 513MiB 100%
fi
# Wait for partitions to appear
sleep 2
partprobe "$disk"
sleep 1
# Determine partition names (nvme vs sd)
if [[ "$disk" == *"nvme"* ]]; then
EFI_PART="${disk}p1"
# Determine partition names (nvme vs sd vs mmcblk)
if [[ "$disk" == *"nvme"* ]] || [[ "$disk" == *"mmcblk"* ]]; then
BOOT_PART="${disk}p1"
ROOT_PART="${disk}p2"
else
EFI_PART="${disk}1"
BOOT_PART="${disk}1"
ROOT_PART="${disk}2"
fi
log "Created partitions: EFI=$EFI_PART, Root=$ROOT_PART"
# For UEFI systems, BOOT_PART is the EFI partition
if [ "$BOOT_TYPE" = "uefi" ]; then
EFI_PART="$BOOT_PART"
fi
log "Created partitions: Boot=$BOOT_PART, Root=$ROOT_PART"
}
# Format partitions
format_partitions() {
log "Formatting partitions..."
mkfs.fat -F 32 -n "EFI" "$EFI_PART"
if [ "$BOOT_TYPE" = "rpi" ]; then
mkfs.fat -F 32 -n "boot" "$BOOT_PART"
else
mkfs.fat -F 32 -n "EFI" "$EFI_PART"
fi
mkfs.ext4 -F -L "EcoOS" "$ROOT_PART"
log "Partitions formatted"
@@ -240,8 +303,15 @@ mount_partitions() {
mkdir -p /mnt/target
mount "$ROOT_PART" /mnt/target
mkdir -p /mnt/target/boot/efi
mount "$EFI_PART" /mnt/target/boot/efi
if [ "$BOOT_TYPE" = "rpi" ]; then
# Raspberry Pi mounts boot at /boot
mkdir -p /mnt/target/boot
mount "$BOOT_PART" /mnt/target/boot
else
# UEFI systems mount EFI at /boot/efi
mkdir -p /mnt/target/boot/efi
mount "$EFI_PART" /mnt/target/boot/efi
fi
log "Partitions mounted at /mnt/target"
}
@@ -292,14 +362,22 @@ configure_system() {
# Get UUIDs
local root_uuid=$(blkid -s UUID -o value "$ROOT_PART")
local efi_uuid=$(blkid -s UUID -o value "$EFI_PART")
local boot_uuid=$(blkid -s UUID -o value "$BOOT_PART")
# Create fstab
cat > /mnt/target/etc/fstab << EOF
# Create fstab based on boot type
if [ "$BOOT_TYPE" = "rpi" ]; then
cat > /mnt/target/etc/fstab << EOF
# EcoOS fstab - Raspberry Pi
UUID=$root_uuid / ext4 defaults,noatime 0 1
UUID=$boot_uuid /boot vfat defaults 0 2
EOF
else
cat > /mnt/target/etc/fstab << EOF
# EcoOS fstab
UUID=$root_uuid / ext4 defaults,noatime 0 1
UUID=$efi_uuid /boot/efi vfat umask=0077 0 1
UUID=$boot_uuid /boot/efi vfat umask=0077 0 1
EOF
fi
# Set hostname
echo "$HOSTNAME" > /mnt/target/etc/hostname
@@ -406,9 +484,89 @@ NETEOF
log "System configured"
}
# Configure Raspberry Pi boot files
configure_rpi_boot() {
log "Configuring Raspberry Pi boot files..."
local root_uuid=$(blkid -s UUID -o value "$ROOT_PART")
# Copy kernel and initrd to boot partition
local kernel=$(ls /mnt/target/boot/vmlinuz-* 2>/dev/null | sort -V | tail -1)
local initrd=$(ls /mnt/target/boot/initrd.img-* 2>/dev/null | sort -V | tail -1)
if [ -n "$kernel" ]; then
cp "$kernel" /mnt/target/boot/vmlinuz
log "Copied kernel: $(basename $kernel)"
fi
if [ -n "$initrd" ]; then
cp "$initrd" /mnt/target/boot/initrd.img
log "Copied initrd: $(basename $initrd)"
fi
# Copy device tree blobs
local dtb_dir=$(ls -d /mnt/target/usr/lib/linux-image-*-raspi 2>/dev/null | tail -1)
if [ -d "$dtb_dir/broadcom" ]; then
cp "$dtb_dir/broadcom"/*.dtb /mnt/target/boot/ 2>/dev/null || true
log "Copied device tree blobs"
fi
if [ -d "$dtb_dir/overlays" ]; then
mkdir -p /mnt/target/boot/overlays
cp -r "$dtb_dir/overlays"/* /mnt/target/boot/overlays/ 2>/dev/null || true
log "Copied device tree overlays"
fi
# Copy Pi firmware files
if [ -d /mnt/target/usr/lib/raspi-firmware ]; then
cp /mnt/target/usr/lib/raspi-firmware/*.bin /mnt/target/boot/ 2>/dev/null || true
cp /mnt/target/usr/lib/raspi-firmware/*.elf /mnt/target/boot/ 2>/dev/null || true
cp /mnt/target/usr/lib/raspi-firmware/*.dat /mnt/target/boot/ 2>/dev/null || true
log "Copied Raspberry Pi firmware"
fi
# Create config.txt
cat > /mnt/target/boot/config.txt << 'EOF'
# EcoOS Raspberry Pi Configuration
# Supports Pi 3, 4, and 5
# Enable 64-bit mode
arm_64bit=1
# Kernel and initrd
kernel=vmlinuz
initramfs initrd.img followkernel
# Enable serial console for debugging
enable_uart=1
# GPU/display settings
dtoverlay=vc4-kms-v3d
gpu_mem=256
# USB and power settings (Pi 4/5)
max_usb_current=1
# Audio
dtparam=audio=on
# Camera/display interfaces
camera_auto_detect=1
display_auto_detect=1
# Pi 5 specific (ignored on older models)
[pi5]
dtoverlay=dwc2,dr_mode=host
EOF
# Create cmdline.txt with root UUID
echo "console=serial0,115200 console=tty1 root=UUID=$root_uuid rootfstype=ext4 fsck.repair=yes rootwait quiet splash" > /mnt/target/boot/cmdline.txt
log "Raspberry Pi boot configured"
}
# Install bootloader
install_bootloader() {
log "Installing GRUB bootloader..."
log "Installing bootloader for $ARCH_TYPE ($BOOT_TYPE)..."
# Mount necessary filesystems for chroot
mount --bind /dev /mnt/target/dev
@@ -417,22 +575,7 @@ install_bootloader() {
mount --bind /sys /mnt/target/sys
mount --bind /run /mnt/target/run
# Fix GRUB default config - remove casper/live boot parameters and add serial console
if [ -f /mnt/target/etc/default/grub ]; then
# Remove any boot=casper or live-related parameters
sed -i 's/boot=casper//g' /mnt/target/etc/default/grub
# Update GRUB_CMDLINE_LINUX_DEFAULT with serial console for debugging
sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0,115200n8"/' /mnt/target/etc/default/grub
# If line doesn't exist, add it
if ! grep -q "GRUB_CMDLINE_LINUX_DEFAULT" /mnt/target/etc/default/grub; then
echo 'GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0,115200n8"' >> /mnt/target/etc/default/grub
fi
# Enable serial terminal in GRUB
echo 'GRUB_TERMINAL="console serial"' >> /mnt/target/etc/default/grub
echo 'GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' >> /mnt/target/etc/default/grub
fi
# Disable casper-related services
# Disable casper-related services (common to all architectures)
log "Disabling live boot services..."
chroot /mnt/target systemctl disable casper.service 2>/dev/null || true
chroot /mnt/target systemctl disable casper-md5check.service 2>/dev/null || true
@@ -454,11 +597,38 @@ install_bootloader() {
# Ensure proper boot target
chroot /mnt/target systemctl set-default multi-user.target 2>/dev/null || true
# Install GRUB
chroot /mnt/target grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=EcoOS --recheck
if [ "$BOOT_TYPE" = "rpi" ]; then
# Raspberry Pi uses native bootloader (no GRUB)
configure_rpi_boot
else
# UEFI systems use GRUB
log "Installing GRUB bootloader..."
# Generate GRUB config
chroot /mnt/target update-grub
# Fix GRUB default config - remove casper/live boot parameters and add serial console
if [ -f /mnt/target/etc/default/grub ]; then
# Remove any boot=casper or live-related parameters
sed -i 's/boot=casper//g' /mnt/target/etc/default/grub
# Update GRUB_CMDLINE_LINUX_DEFAULT with serial console for debugging
sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0,115200n8"/' /mnt/target/etc/default/grub
# If line doesn't exist, add it
if ! grep -q "GRUB_CMDLINE_LINUX_DEFAULT" /mnt/target/etc/default/grub; then
echo 'GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0,115200n8"' >> /mnt/target/etc/default/grub
fi
# Enable serial terminal in GRUB
echo 'GRUB_TERMINAL="console serial"' >> /mnt/target/etc/default/grub
echo 'GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' >> /mnt/target/etc/default/grub
fi
# Install GRUB based on architecture
if [ "$ARCH_TYPE" = "amd64" ]; then
chroot /mnt/target grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=EcoOS --recheck
elif [ "$ARCH_TYPE" = "arm64" ]; then
chroot /mnt/target grub-install --target=arm64-efi --efi-directory=/boot/efi --bootloader-id=EcoOS --recheck
fi
# Generate GRUB config
chroot /mnt/target update-grub
fi
# Cleanup mounts (use lazy unmount for stubborn mounts, reverse order)
sync
@@ -478,8 +648,12 @@ cleanup_and_reboot() {
# Sync disks
sync
# Unmount
umount /mnt/target/boot/efi
# Unmount based on boot type
if [ "$BOOT_TYPE" = "rpi" ]; then
umount /mnt/target/boot
else
umount /mnt/target/boot/efi
fi
umount /mnt/target
echo ""