From 8f3ffcb87dec32b6ff47339ea43d2e265019fd2f Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Tue, 15 Jul 2025 21:02:48 -0400 Subject: [PATCH] Updated install to disk. --- usr/local/bin/install_to_disk.sh | 282 ++++++++++++++++++++----------- 1 file changed, 180 insertions(+), 102 deletions(-) diff --git a/usr/local/bin/install_to_disk.sh b/usr/local/bin/install_to_disk.sh index 0bfe123..60d819b 100644 --- a/usr/local/bin/install_to_disk.sh +++ b/usr/local/bin/install_to_disk.sh @@ -1,30 +1,19 @@ -#!/bin/bash +#!/usr/bin/env bash -# Stormux Gaming Image Disk Installer -# WARNING: This will completely wipe the selected disk! +# Stormux Gaming Image - Rsync-based Disk Installer +# Copies the live system to a target disk using rsync set -e -# Function to print messages -print_message() { +# Text output functions +speak_and_echo() { echo "$1" + spd-say "$1" 2>/dev/null || true } -# Function to get user confirmation -get_confirmation() { - local prompt="$1" - local required_response="$2" - local response - - while true; do - print_message "$prompt" - read -r response - if [[ "$response" == "$required_response" ]]; then - return 0 - else - print_message "Response must be exactly: $required_response" - fi - done +error_exit() { + speak_and_echo "Error: $1" + exit 1 } # Function to detect available disks @@ -57,50 +46,42 @@ get_disk_model() { lsblk -dpno MODEL "$disk" 2>/dev/null | tr -d ' ' || echo "Unknown" } -# Check if running as root -if [[ $EUID -ne 0 ]]; then - print_message "This script must be run as root." - print_message "Please run: sudo $0" - exit 1 -fi - # Welcome message -print_message "" -print_message "=== Stormux Gaming Image Installer ===" -print_message "WARNING: This installer will COMPLETELY WIPE the selected disk!" -print_message "All data on the target disk will be permanently lost." +clear +speak_and_echo "Stormux Gaming Image Disk Installer" +speak_and_echo "This will install the current live system to a hard disk." +echo +speak_and_echo "WARNING: This will completely erase the target disk!" # Detect available disks -print_message "" -print_message "Detecting available disks..." +speak_and_echo "Detecting available disks..." mapfile -t available_disks < <(detect_disks) if [[ ${#available_disks[@]} -eq 0 ]]; then - print_message "No suitable disks found!" - exit 1 + error_exit "No suitable disks found!" fi # Display available disks -print_message "" -print_message "Available disks:" +echo +speak_and_echo "Available disks:" for i in "${!available_disks[@]}"; do disk="${available_disks[$i]}" size=$(get_disk_size "$disk") model=$(get_disk_model "$disk") - print_message "$((i+1)). $disk - $size - $model" "$((i+1)). $disk - $size - $model" + echo "$((i+1)). $disk - $size - $model" done # Get disk selection while true; do - print_message "" - print_message "Enter the number of the disk to install to:" + echo + speak_and_echo "Enter the number of the disk to install to:" read -r selection if [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -le ${#available_disks[@]} ]]; then selected_disk="${available_disks[$((selection-1))]}" break else - print_message "Invalid selection. Please enter a number between 1 and ${#available_disks[@]}." + speak_and_echo "Invalid selection. Please enter a number between 1 and ${#available_disks[@]}." fi done @@ -108,86 +89,183 @@ done selected_size=$(get_disk_size "$selected_disk") selected_model=$(get_disk_model "$selected_disk") -print_message "" -print_message "FINAL WARNING:" -print_message "You have selected: $selected_disk ($selected_size, $selected_model)" -print_message "ALL DATA ON THIS DISK WILL BE PERMANENTLY DESTROYED!" +echo +speak_and_echo "FINAL WARNING:" +speak_and_echo "You have selected: $selected_disk ($selected_size, $selected_model)" +speak_and_echo "ALL DATA ON THIS DISK WILL BE PERMANENTLY DESTROYED!" +echo +speak_and_echo "Type 'yes' to continue or any other key to cancel:" +read -r CONFIRM -get_confirmation "Type 'DESTROY ALL DATA' to continue (case sensitive): " "DESTROY ALL DATA" +if [[ "$CONFIRM" != "yes" ]]; then + speak_and_echo "Installation cancelled." + exit 0 +fi -print_message "" -print_message "Starting installation to $selected_disk..." +# Check if we're on UEFI or BIOS +if [[ -d /sys/firmware/efi ]]; then + BOOT_MODE="UEFI" + speak_and_echo "Detected UEFI boot mode" +else + BOOT_MODE="BIOS" + speak_and_echo "Detected BIOS boot mode" +fi + +speak_and_echo "Starting installation to $selected_disk..." # Unmount any existing partitions on the target disk -print_message "Unmounting any existing partitions..." +speak_and_echo "Unmounting any existing partitions..." umount "${selected_disk}"* 2>/dev/null || true -# Create partition table and partitions -print_message "Creating partition table..." -parted -s "$selected_disk" mklabel gpt -parted -s "$selected_disk" mkpart primary fat32 1MiB 513MiB -parted -s "$selected_disk" set 1 esp on -parted -s "$selected_disk" mkpart primary ext4 513MiB 100% - -# Get partition names -if [[ "$selected_disk" =~ nvme|mmcblk ]]; then - boot_partition="${selected_disk}p1" - root_partition="${selected_disk}p2" +# Create partition table +speak_and_echo "Creating partition table..." +if [[ "$BOOT_MODE" == "UEFI" ]]; then + # UEFI: GPT with EFI system partition + parted -s "$selected_disk" mklabel gpt + parted -s "$selected_disk" mkpart primary fat32 1MiB 513MiB + parted -s "$selected_disk" set 1 esp on + parted -s "$selected_disk" mkpart primary ext4 513MiB 100% + + # Set partition variables + if [[ "$selected_disk" =~ nvme|mmcblk ]]; then + EFI_PART="${selected_disk}p1" + ROOT_PART="${selected_disk}p2" + else + EFI_PART="${selected_disk}1" + ROOT_PART="${selected_disk}2" + fi else - boot_partition="${selected_disk}1" - root_partition="${selected_disk}2" + # BIOS: MBR with boot flag + parted -s "$selected_disk" mklabel msdos + parted -s "$selected_disk" mkpart primary ext4 1MiB 100% + parted -s "$selected_disk" set 1 boot on + + # Set partition variables + if [[ "$selected_disk" =~ nvme|mmcblk ]]; then + ROOT_PART="${selected_disk}p1" + else + ROOT_PART="${selected_disk}1" + fi fi +# Wait for kernel to recognize partitions +sleep 2 +partprobe "$selected_disk" +sleep 2 + # Format partitions -print_message "Formatting partitions..." -mkfs.fat -F32 "$boot_partition" -mkfs.ext4 -F "$root_partition" +speak_and_echo "Formatting partitions..." +if [[ "$BOOT_MODE" == "UEFI" ]]; then + mkfs.fat -F32 -n "STORMUX-EFI" "$EFI_PART" +fi +mkfs.ext4 -F -L "STORMUX-ROOT" "$ROOT_PART" -# Create mount points and mount -mkdir -p /mnt/stormux-install -mount "$root_partition" /mnt/stormux-install -mkdir -p /mnt/stormux-install/boot -mount "$boot_partition" /mnt/stormux-install/boot +# Create mount points +MOUNT_ROOT="/mnt/install_target" +mkdir -p "$MOUNT_ROOT" -# Copy system files -print_message "Copying system files... This may take several minutes." -if [[ -f /run/archiso/img_dev ]]; then - # Extract from squashfs - unsquashfs -f -d /mnt/stormux-install /run/archiso/sfs/airootfs/airootfs.sfs -else - # Fallback: copy from live system - rsync -aHAXS --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / /mnt/stormux-install/ +# Mount root partition +speak_and_echo "Mounting partitions..." +mount "$ROOT_PART" "$MOUNT_ROOT" + +# Mount EFI partition if UEFI +if [[ "$BOOT_MODE" == "UEFI" ]]; then + mkdir -p "$MOUNT_ROOT/boot/efi" + mount "$EFI_PART" "$MOUNT_ROOT/boot/efi" fi -# Configure for installed system -print_message "Configuring system for installed boot..." +# Copy system using rsync +speak_and_echo "Copying system files... This may take several minutes." +rsync -avx \ + --exclude=/tmp/* \ + --exclude=/proc/* \ + --exclude=/sys/* \ + --exclude=/dev/* \ + --exclude=/run/* \ + --exclude=/var/tmp/* \ + --exclude=/var/log/journal/* \ + --exclude=/mnt/* \ + --exclude=/media/* \ + --exclude=/lost+found \ + --exclude=/home/stormux/.cache/* \ + --exclude=/home/stormux/Downloads/* \ + / "$MOUNT_ROOT/" -# Remove live-specific files and services -rm -f /mnt/stormux-install/etc/systemd/system/multi-user.target.wants/choose-mirror.service -rm -rf /mnt/stormux-install/etc/systemd/system/etc-pacman.d-gnupg.mount +# Create necessary directories +speak_and_echo "Creating system directories..." +mkdir -p "$MOUNT_ROOT"/{tmp,proc,sys,dev,run,var/tmp,var/log/journal,mnt,media} # Generate fstab -genfstab -U /mnt/stormux-install >> /mnt/stormux-install/etc/fstab +speak_and_echo "Generating fstab..." +ROOT_UUID=$(blkid -s UUID -o value "$ROOT_PART") +cat > "$MOUNT_ROOT/etc/fstab" << EOF +# Static information about the filesystems. +# See fstab(5) for details. -# Install and configure GRUB -print_message "Installing bootloader..." -arch-chroot /mnt/stormux-install grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=stormux -arch-chroot /mnt/stormux-install grub-mkconfig -o /boot/grub/grub.cfg +# +UUID=$ROOT_UUID / ext4 rw,relatime 0 1 +EOF -# Set hostname -echo "stormux-gaming" > /mnt/stormux-install/etc/hostname +if [[ "$BOOT_MODE" == "UEFI" ]]; then + EFI_UUID=$(blkid -s UUID -o value "$EFI_PART") + echo "UUID=$EFI_UUID /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2" >> "$MOUNT_ROOT/etc/fstab" +fi -# Enable necessary services -arch-chroot /mnt/stormux-install systemctl enable NetworkManager -arch-chroot /mnt/stormux-install systemctl enable pipewire pipewire-pulse -arch-chroot /mnt/stormux-install systemctl enable speech-dispatcher -arch-chroot /mnt/stormux-install systemctl enable fenrirscreenreader +# Install bootloader +speak_and_echo "Installing bootloader..." +arch-chroot "$MOUNT_ROOT" /bin/bash << EOF +# Update package database and install GRUB +pacman -Sy --noconfirm -# Cleanup -umount -R /mnt/stormux-install -rmdir /mnt/stormux-install +if [[ "$BOOT_MODE" == "UEFI" ]]; then + # UEFI installation + pacman -S --needed --noconfirm grub efibootmgr + grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Stormux +else + # BIOS installation + pacman -S --needed --noconfirm grub + grub-install --target=i386-pc "$selected_disk" +fi -print_message "" -print_message "Installation completed successfully!" -print_message "You can now reboot and remove the installation media." -print_message "The system will boot directly into the Stormux Gaming environment." +# Generate GRUB configuration with accessibility +grub-mkconfig -o /boot/grub/grub.cfg + +# Enable accessibility in GRUB by default +if ! grep -q "GRUB_CMDLINE_LINUX_DEFAULT.*accessibility=on" /etc/default/grub; then + sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="accessibility=on /' /etc/default/grub + grub-mkconfig -o /boot/grub/grub.cfg +fi + +# Enable essential services +systemctl enable NetworkManager +systemctl enable pipewire.service +systemctl enable pipewire-pulse.service +systemctl enable unmute-audio.service +systemctl enable shutdown-sound.service +systemctl enable fenrirscreenreader-tty.service +systemctl disable espeakup.service + +# Set up user services +systemctl --global enable pipewire.service +systemctl --global enable pipewire-pulse.service +EOF + +# Remove firstboot marker if it exists +rm -f "$MOUNT_ROOT/home/stormux/.firstboot" + +# Clean up mount points +speak_and_echo "Cleaning up..." +if [[ "$BOOT_MODE" == "UEFI" ]]; then + umount "$MOUNT_ROOT/boot/efi" +fi +umount "$MOUNT_ROOT" +rmdir "$MOUNT_ROOT" + +# Success message +speak_and_echo "Installation completed successfully!" +echo +speak_and_echo "The system has been installed to $selected_disk" +speak_and_echo "You can now reboot and remove the USB drive." +echo +speak_and_echo "Press Enter to continue..." +read -r