Attempt to fix more problems with the install to disk script.

This commit is contained in:
Storm Dragon
2025-10-11 14:25:35 -04:00
parent 6509c5575f
commit 75c8cac81d
+369 -248
View File
@@ -1,20 +1,49 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Stormux Gaming Image - USB to Disk Cloner # Stormux Gaming Image - Ultra-Reliable Disk Installer
# Clones the entire USB system to an internal disk # Clones USB system to internal disk with proper bootloader installation
set -e set -euo pipefail
# Initialize logging
LOGDIR="/home/stormux/Logs"
LOGFILE="$LOGDIR/install_to_disk_$(date +%Y-%m-%d_%H-%M-%S).log"
mkdir -p "$LOGDIR"
# Logging function
log() {
local msg
msg="[$(date +%H:%M:%S)] $*"
echo "$msg" | tee -a "$LOGFILE"
}
log_error() {
local msg
msg="[ERROR] $*"
echo "$msg" | tee -a "$LOGFILE" >&2
}
error_exit() { error_exit() {
echo "Error: $1" log_error "$1"
echo "Installation failed. Log file: $LOGFILE"
restore_speech
exit 1 exit 1
} }
# Speech management
disable_speech() {
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock 2>/dev/null || true
}
restore_speech() {
echo "command toggletempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock 2>/dev/null || true
}
# Function to find the source USB device # Function to find the source USB device
find_source_device() { find_source_device() {
# Look for the device we're currently running from
local root_device local root_device
root_device=$(findmnt -n -o SOURCE /) root_device=$(findmnt -n -o SOURCE /)
if [[ "$root_device" =~ ^/dev/(sd[a-z]|nvme[0-9]n[0-9]|mmcblk[0-9]) ]]; then if [[ "$root_device" =~ ^/dev/(sd[a-z]|nvme[0-9]n[0-9]|mmcblk[0-9]) ]]; then
# Extract just the device name (remove partition number) # Extract just the device name (remove partition number)
echo "$root_device" | sed 's/[0-9]*$//' | sed 's/p$//' echo "$root_device" | sed 's/[0-9]*$//' | sed 's/p$//'
@@ -34,17 +63,19 @@ find_source_device() {
detect_target_disks() { detect_target_disks() {
local source_device="$1" local source_device="$1"
local disks=() local disks=()
while IFS= read -r disk; do while IFS= read -r disk; do
# Skip if it's a partition, loop device, CD-ROM, or the source device # Skip partitions, loop devices, CD-ROMs, and source device
# For partitions: skip sda1, nvme0n1p1, mmcblk0p1, but keep sda, nvme0n1, mmcblk0 if [[ ! "$disk" =~ (sd[a-z][0-9]+|nvme[0-9]+n[0-9]+p[0-9]+|mmcblk[0-9]+p[0-9]+)$ ]] && \
if [[ ! "$disk" =~ (sd[a-z][0-9]+|nvme[0-9]+n[0-9]+p[0-9]+|mmcblk[0-9]+p[0-9]+)$ ]] && [[ ! "$disk" =~ ^/dev/loop ]] && [[ ! "$disk" =~ ^/dev/sr ]] && [[ "$disk" != "$source_device" ]]; then [[ ! "$disk" =~ ^/dev/loop ]] && \
[[ ! "$disk" =~ ^/dev/sr ]] && \
[[ "$disk" != "$source_device" ]]; then
if [[ -b "$disk" ]]; then if [[ -b "$disk" ]]; then
disks+=("$disk") disks+=("$disk")
fi fi
fi fi
done < <(lsblk -dpno NAME 2>/dev/null) done < <(lsblk -dpno NAME 2>/dev/null)
printf '%s\n' "${disks[@]}" printf '%s\n' "${disks[@]}"
} }
@@ -58,147 +89,278 @@ get_disk_info() {
echo "$size - $model" echo "$size - $model"
} }
# Function to regenerate UUIDs and rename partition labels to prevent boot conflicts # Function to detect partitions by filesystem type
regenerate_partition_identifiers() { # shellcheck disable=SC2154
local target_device="$1" detect_partitions() {
echo "Regenerating partition UUIDs and labels to prevent boot conflicts..." local device="$1"
# shellcheck disable=SC2178
# Arrays to store old and new UUIDs for fstab update local -n result=$2 # nameref to associative array
declare -A old_uuids
declare -A new_uuids log "Detecting partition structure on $device..."
# Get all partitions on the target device # Get all partitions
local partitions=() while IFS= read -r line; do
while IFS= read -r partition; do local part fstype label
if [[ "$partition" != "$target_device" && "$partition" =~ ^${target_device}.+ ]]; then part=$(echo "$line" | awk '{print $1}')
partitions+=("$partition") fstype=$(echo "$line" | awk '{print $2}')
fi label=$(echo "$line" | awk '{print $3}')
done < <(lsblk -lpno NAME "$target_device" 2>/dev/null)
# Skip if it's the device itself, not a partition
# Process each partition [[ "$part" == "$device" ]] && continue
for partition in "${partitions[@]}"; do
local fstype
local current_label
local current_uuid
fstype=$(lsblk -no FSTYPE "$partition" 2>/dev/null)
current_label=$(lsblk -no LABEL "$partition" 2>/dev/null)
current_uuid=$(lsblk -no UUID "$partition" 2>/dev/null)
# Skip if no filesystem
[[ -z "$fstype" ]] && continue
# Store old UUID if it exists
[[ -n "$current_uuid" ]] && old_uuids["$partition"]="$current_uuid"
# Determine new label based on current label and add -HDD suffix
local new_label=""
if [[ -n "$current_label" ]]; then
case "$current_label" in
"STORMUX"|"stormux")
new_label="STORMUX-HDD"
;;
"BOOT"|"boot"|"ESP")
new_label="BOOT-HDD"
;;
*)
# For any other label, just add -HDD suffix, truncate if too long
new_label="${current_label}-HDD"
;;
esac
fi
# Handle the known 3-partition structure
case "$fstype" in case "$fstype" in
"vfat"|"fat32"|"fat16") "")
# Partition 2: FAT32 EFI boot partition # BIOS boot partition (no filesystem)
if [[ -n "$new_label" ]]; then result[bios]="$part"
new_label="${new_label:0:11}" # FAT32 has 11 character limit log " BIOS boot partition: $part"
if command -v fatlabel >/dev/null 2>&1; then ;;
sudo fatlabel "$partition" "$new_label" 2>/dev/null || echo "Warning: Could not rename FAT partition $partition" "vfat")
fi # EFI partition
fi result[efi]="$part"
# Generate new UUID for FAT log " EFI partition: $part (label: ${label:-none})"
if command -v mlabel >/dev/null 2>&1; then
sudo mlabel -s -i "$partition" :: 2>/dev/null || echo "Warning: Could not change FAT serial on $partition"
fi
;; ;;
"ext4") "ext4")
# Partition 3: ext4 root filesystem # Root partition
if [[ -n "$new_label" ]]; then result[root]="$part"
new_label="${new_label:0:16}" # ext4 has 16 character limit log " Root partition: $part (label: ${label:-none})"
if command -v tune2fs >/dev/null 2>&1; then
sudo tune2fs -L "$new_label" "$partition" 2>/dev/null || echo "Warning: Could not rename ext4 partition $partition"
fi
fi
# Generate new UUID for ext4
if command -v tune2fs >/dev/null 2>&1; then
sudo tune2fs -U random "$partition" 2>/dev/null || echo "Warning: Could not change UUID on $partition"
fi
;;
"")
# Partition 1: No filesystem (skip)
echo "Skipping partition $partition (no filesystem)"
continue
;; ;;
*) *)
echo "Warning: Unexpected filesystem type '$fstype' on $partition" log " Unknown partition type: $part ($fstype)"
continue
;; ;;
esac esac
done < <(lsblk -no NAME,FSTYPE,LABEL "$device" 2>/dev/null | tail -n +2)
# Get the new UUID after regeneration
# Validate we found all required partitions
if [[ -z "${result[root]:-}" ]]; then
return 1
fi
return 0
}
# Function to regenerate UUIDs and update labels
regenerate_partition_identifiers() {
local device="$1"
local -n partitions=$2
declare -A uuid_map
log "Regenerating partition UUIDs and labels..."
# Process EFI partition
if [[ -n "${partitions[efi]:-}" ]]; then
local efi_part="${partitions[efi]}"
local old_uuid
old_uuid=$(lsblk -no UUID "$efi_part" 2>/dev/null || echo "")
# Change label
if command -v fatlabel >/dev/null 2>&1; then
sudo fatlabel "$efi_part" "BOOT-HDD" 2>/dev/null || log "Warning: Could not rename EFI partition"
fi
# Generate new UUID for FAT
if command -v mlabel >/dev/null 2>&1; then
sudo mlabel -s -i "$efi_part" :: 2>/dev/null || log "Warning: Could not change FAT serial"
fi
local new_uuid local new_uuid
new_uuid=$(lsblk -no UUID "$partition" 2>/dev/null) new_uuid=$(lsblk -no UUID "$efi_part" 2>/dev/null || echo "")
[[ -n "$new_uuid" ]] && new_uuids["$partition"]="$new_uuid"
if [[ -n "$old_uuid" && -n "$new_uuid" ]]; then
if [[ -n "$current_label" && -n "$new_label" ]]; then uuid_map["$old_uuid"]="$new_uuid"
echo "Updated partition $partition: '$current_label' -> '$new_label'" log " EFI UUID: $old_uuid -> $new_uuid"
fi fi
if [[ -n "$current_uuid" && -n "$new_uuid" && "$current_uuid" != "$new_uuid" ]]; then fi
echo "Regenerated UUID for $partition: $current_uuid -> $new_uuid"
# Process root partition
if [[ -n "${partitions[root]:-}" ]]; then
local root_part="${partitions[root]}"
local old_uuid
old_uuid=$(lsblk -no UUID "$root_part" 2>/dev/null || echo "")
# Change label and UUID
if command -v tune2fs >/dev/null 2>&1; then
sudo tune2fs -L "STORMUX-HDD" "$root_part" 2>/dev/null || log "Warning: Could not rename root partition"
sudo tune2fs -U random "$root_part" 2>/dev/null || log "Warning: Could not change root UUID"
fi fi
done
local new_uuid
# Return the UUID mappings for fstab update new_uuid=$(lsblk -no UUID "$root_part" 2>/dev/null || echo "")
for partition in "${!old_uuids[@]}"; do
if [[ -n "${new_uuids[$partition]}" ]]; then if [[ -n "$old_uuid" && -n "$new_uuid" ]]; then
echo "UUID_MAPPING:${old_uuids[$partition]}:${new_uuids[$partition]}" uuid_map["$old_uuid"]="$new_uuid"
log " Root UUID: $old_uuid -> $new_uuid"
fi fi
fi
# Return UUID mappings
for old in "${!uuid_map[@]}"; do
echo "UUID_MAP:$old:${uuid_map[$old]}"
done done
} }
# Function to update fstab with new UUIDs
update_fstab() {
local mount_point="$1"
shift
local mappings=("$@")
log "Updating fstab with new UUIDs..."
local fstab="$mount_point/etc/fstab"
if [[ ! -f "$fstab" ]]; then
log_error "fstab not found at $fstab"
return 1
fi
# Backup original
sudo cp "$fstab" "$fstab.backup" || log "Warning: Could not backup fstab"
# Apply UUID mappings
local temp_fstab
temp_fstab=$(mktemp)
sudo cp "$fstab" "$temp_fstab"
for mapping in "${mappings[@]}"; do
if [[ "$mapping" =~ ^UUID_MAP:([^:]+):([^:]+)$ ]]; then
local old_uuid="${BASH_REMATCH[1]}"
local new_uuid="${BASH_REMATCH[2]}"
sed -i "s/UUID=$old_uuid/UUID=$new_uuid/g" "$temp_fstab"
log " Updated fstab: $old_uuid -> $new_uuid"
fi
done
sudo cp "$temp_fstab" "$fstab"
rm -f "$temp_fstab"
log "fstab updated successfully"
return 0
}
# Function to install GRUB in chroot
install_grub() {
local mount_point="$1"
local target_device="$2"
local -n parts=$3
log "Installing GRUB bootloader to $target_device..."
# Ensure EFI partition is mounted inside chroot
if [[ -n "${parts[efi]:-}" ]]; then
sudo mkdir -p "$mount_point/boot"
if ! mountpoint -q "$mount_point/boot"; then
sudo mount "${parts[efi]}" "$mount_point/boot" || error_exit "Failed to mount EFI partition"
log " Mounted EFI partition at /boot"
fi
fi
# Bind mount necessary filesystems for chroot
sudo mount --bind /dev "$mount_point/dev" || error_exit "Failed to bind mount /dev"
sudo mount --bind /sys "$mount_point/sys" || error_exit "Failed to bind mount /sys"
sudo mount --bind /proc "$mount_point/proc" || error_exit "Failed to bind mount /proc"
log " Prepared chroot environment"
# Install GRUB for BIOS (allow to fail gracefully)
log " Installing GRUB for BIOS boot (warnings expected on UEFI systems)..."
if sudo arch-chroot "$mount_point" grub-install --target=i386-pc --recheck "$target_device" 2>&1 | tee -a "$LOGFILE"; then
log " BIOS boot installation succeeded"
else
log " BIOS boot installation completed with warnings (expected on UEFI systems)"
fi
# Install GRUB for UEFI (must succeed)
log " Installing GRUB for UEFI boot..."
if ! sudo arch-chroot "$mount_point" grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=STORMUX-HDD --recheck 2>&1 | tee -a "$LOGFILE"; then
error_exit "UEFI GRUB installation failed"
fi
log " UEFI boot installation succeeded"
# Generate GRUB configuration
log " Generating GRUB configuration..."
if ! sudo arch-chroot "$mount_point" grub-mkconfig -o /boot/grub/grub.cfg 2>&1 | tee -a "$LOGFILE"; then
error_exit "GRUB configuration generation failed"
fi
log " GRUB configuration generated successfully"
# Unmount bind mounts
sudo umount "$mount_point/proc" 2>/dev/null || true
sudo umount "$mount_point/sys" 2>/dev/null || true
sudo umount "$mount_point/dev" 2>/dev/null || true
log "GRUB installation completed successfully"
return 0
}
# Function to validate installation
validate_installation() {
local mount_point="$1"
log "Validating installation..."
# Check fstab exists and has valid entries
if [[ ! -f "$mount_point/etc/fstab" ]]; then
log_error "fstab not found"
return 1
fi
# Check GRUB config exists
if [[ ! -f "$mount_point/boot/grub/grub.cfg" ]]; then
log_error "GRUB configuration not found"
return 1
fi
# Check for baremetal marker
if [[ ! -f "$mount_point/home/stormux/.baremetal" ]]; then
log_error "Baremetal marker not found"
return 1
fi
log "Validation passed"
return 0
}
###################
# Main Installation
###################
# Welcome message
clear clear
echo "Stormux Gaming Image - USB to Disk Installer" log "========================================"
echo "This will clone the entire USB system to an internal disk." log "Stormux Gaming Image - Disk Installer"
log "========================================"
log "Log file: $LOGFILE"
echo
echo "This will clone the USB system to an internal disk."
echo echo
# Find source device # Find source device
echo "Detecting source USB device..." log "Detecting source USB device..."
SOURCE_DEVICE=$(find_source_device) SOURCE_DEVICE=$(find_source_device)
if [[ -z "$SOURCE_DEVICE" ]]; then if [[ -z "$SOURCE_DEVICE" ]]; then
error_exit "Could not detect source USB device" error_exit "Could not detect source USB device"
fi fi
SOURCE_SIZE=$(lsblk -dpno SIZE "$SOURCE_DEVICE" 2>/dev/null | tr -d ' ') SOURCE_SIZE=$(lsblk -dpno SIZE "$SOURCE_DEVICE" 2>/dev/null | tr -d ' ')
log "Source device: $SOURCE_DEVICE ($SOURCE_SIZE)"
echo "Source device: $SOURCE_DEVICE ($SOURCE_SIZE)" echo "Source device: $SOURCE_DEVICE ($SOURCE_SIZE)"
echo echo
# Detect target disks # Detect target disks
echo "Detecting target disks..." log "Detecting target disks..."
mapfile -t target_disks < <(detect_target_disks "$SOURCE_DEVICE") mapfile -t target_disks < <(detect_target_disks "$SOURCE_DEVICE")
if [[ ${#target_disks[@]} -eq 0 ]]; then if [[ ${#target_disks[@]} -eq 0 ]]; then
error_exit "No suitable target disks found (excluding source USB)" error_exit "No suitable target disks found"
fi fi
# Display target disks # Display target disks
echo "Available target disks:" echo "Available target disks:"
log "Available target disks:"
for i in "${!target_disks[@]}"; do for i in "${!target_disks[@]}"; do
disk="${target_disks[$i]}" disk="${target_disks[$i]}"
info=$(get_disk_info "$disk") info=$(get_disk_info "$disk")
echo "$((i+1)). $disk - $info" echo "$((i+1)). $disk - $info"
log " $((i+1)). $disk - $info"
done done
# Get disk selection # Get disk selection
@@ -206,7 +368,7 @@ while true; do
echo echo
echo "Enter the number of the disk to install to:" echo "Enter the number of the disk to install to:"
read -r selection read -r selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -le ${#target_disks[@]} ]]; then if [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -le ${#target_disks[@]} ]]; then
TARGET_DEVICE="${target_disks[$((selection-1))]}" TARGET_DEVICE="${target_disks[$((selection-1))]}"
break break
@@ -215,12 +377,19 @@ while true; do
fi fi
done done
log "Selected target device: $TARGET_DEVICE"
# Safety check: ensure target != source
if [[ "$TARGET_DEVICE" == "$SOURCE_DEVICE" ]]; then
error_exit "Target device cannot be the same as source device"
fi
# Check target disk size # Check target disk size
TARGET_SIZE_BYTES=$(lsblk -dpno SIZE -b "$TARGET_DEVICE" 2>/dev/null) TARGET_SIZE_BYTES=$(lsblk -dpno SIZE -b "$TARGET_DEVICE" 2>/dev/null)
SOURCE_SIZE_BYTES=$(lsblk -dpno SIZE -b "$SOURCE_DEVICE" 2>/dev/null) SOURCE_SIZE_BYTES=$(lsblk -dpno SIZE -b "$SOURCE_DEVICE" 2>/dev/null)
if [[ "$TARGET_SIZE_BYTES" -lt "$SOURCE_SIZE_BYTES" ]]; then if [[ "$TARGET_SIZE_BYTES" -lt "$SOURCE_SIZE_BYTES" ]]; then
error_exit "Target disk is smaller than source USB. Cannot proceed." error_exit "Target disk is smaller than source USB"
fi fi
# Final confirmation # Final confirmation
@@ -231,181 +400,133 @@ echo "Source: $SOURCE_DEVICE ($SOURCE_SIZE)"
echo "Target: $TARGET_DEVICE ($target_info)" echo "Target: $TARGET_DEVICE ($target_info)"
echo "ALL DATA ON THE TARGET DISK WILL BE PERMANENTLY DESTROYED!" echo "ALL DATA ON THE TARGET DISK WILL BE PERMANENTLY DESTROYED!"
echo echo
log "Final confirmation - Target: $TARGET_DEVICE"
echo "Type 'yes' to continue or any other key to cancel:" echo "Type 'yes' to continue or any other key to cancel:"
read -r CONFIRM read -r CONFIRM
if [[ "$CONFIRM" != "yes" ]]; then if [[ "$CONFIRM" != "yes" ]]; then
log "Installation cancelled by user"
echo "Installation cancelled." echo "Installation cancelled."
exit 0 exit 0
fi fi
# Rely on progress bar beeps for status log "User confirmed installation"
# Disable speech during installation
echo echo
echo "Fenrir will be silent during the install process except for progress beeps." echo "Fenrir will be silent during installation except for progress beeps."
echo "To restore speech if needed, press any key." echo "Press Enter to begin..."
echo "Press Enter to begin installation..."
read -r read -r
echo "command tempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock 2>/dev/null || true disable_speech
# Unmount any mounted partitions on target disk # Unmount any mounted partitions on target disk
echo "Unmounting target disk partitions..." log "Unmounting target disk partitions..."
sudo umount "${TARGET_DEVICE}"* 2>/dev/null || true sudo umount "${TARGET_DEVICE}"* 2>/dev/null || true
# Clone the USB to the target disk # Clone the USB to target disk
log "Starting disk clone operation..."
echo "Cloning USB system to target disk..." echo "Cloning USB system to target disk..."
echo "This will take several minutes depending on USB size and disk speed." echo "This will take several minutes depending on USB size and disk speed."
echo echo
# Use dd to clone the entire device if ! sudo dd if="$SOURCE_DEVICE" of="$TARGET_DEVICE" bs=4M oflag=sync status=progress 2>&1 | tee -a "$LOGFILE"; then
if ! sudo dd if="$SOURCE_DEVICE" of="$TARGET_DEVICE" bs=4M oflag=sync status=progress; then
error_exit "Failed to clone USB to target disk" error_exit "Failed to clone USB to target disk"
fi fi
# Sync to ensure all data is written log "Disk clone completed successfully"
echo "Syncing data to disk..."
# Sync and refresh partition table
log "Syncing data to disk..."
sudo sync sudo sync
# Update the cloned system to remove USB-specific configurations log "Refreshing partition table..."
echo "Finalizing installation..." sudo partprobe "$TARGET_DEVICE" 2>&1 | tee -a "$LOGFILE" || log "Warning: partprobe reported issues"
sudo udevadm settle --timeout=10 || log "Warning: udevadm settle timeout"
sleep 2
# Mount the new root partition to make final adjustments # Detect partition structure
if [[ "$TARGET_DEVICE" =~ (nvme|mmcblk) ]]; then log "Analyzing cloned partition structure..."
TARGET_ROOT_PART="${TARGET_DEVICE}p1" declare -A target_partitions
else if ! detect_partitions "$TARGET_DEVICE" target_partitions; then
TARGET_ROOT_PART="${TARGET_DEVICE}1" error_exit "Failed to detect partition structure on target disk"
fi fi
# Find the actual root partition (might not be partition 1) # Validate partition structure
echo "Searching for ext4 root partition..." if [[ -z "${target_partitions[root]:-}" ]]; then
for part in "${TARGET_DEVICE}"*; do error_exit "Could not find root partition on target disk"
if [[ "$part" != "$TARGET_DEVICE" ]]; then fi
fstype=$(lsblk -no FSTYPE "$part" 2>/dev/null)
echo "Checking $part: filesystem type = $fstype"
if [[ "$fstype" == "ext4" ]]; then
TARGET_ROOT_PART="$part"
echo "Found root partition: $TARGET_ROOT_PART"
break
fi
fi
done
# Regenerate partition UUIDs and labels to prevent boot conflicts with USB log "Partition detection complete:"
echo "Regenerating partition identifiers..." log " BIOS: ${target_partitions[bios]:-none}"
mapfile -t uuid_mappings < <(regenerate_partition_identifiers "$TARGET_DEVICE") log " EFI: ${target_partitions[efi]:-none}"
echo "Found ${#uuid_mappings[@]} UUID mappings to update" log " Root: ${target_partitions[root]}"
# Mount and make final adjustments # Mount root partition
TEMP_MOUNT="/mnt/stormux_target" TEMP_MOUNT="/mnt/stormux_target"
sudo mkdir -p "$TEMP_MOUNT" sudo mkdir -p "$TEMP_MOUNT"
echo "Mounting $TARGET_ROOT_PART for final adjustments..." log "Mounting root partition ${target_partitions[root]}..."
if sudo mount "$TARGET_ROOT_PART" "$TEMP_MOUNT" 2>/dev/null; then if ! sudo mount "${target_partitions[root]}" "$TEMP_MOUNT" 2>&1 | tee -a "$LOGFILE"; then
echo "Successfully mounted target partition" error_exit "Failed to mount root partition"
# Remove any USB-specific markers
sudo rm -f "$TEMP_MOUNT/home/stormux/.firstboot" 2>/dev/null || true
# Create .baremetal marker file to indicate installed system
echo "Creating baremetal system marker..."
sudo touch "$TEMP_MOUNT/home/stormux/.baremetal"
sudo chown stormux:stormux "$TEMP_MOUNT/home/stormux/.baremetal" 2>/dev/null || true
# Set immutable attribute to prevent accidental deletion
sudo chattr +i "$TEMP_MOUNT/home/stormux/.baremetal" 2>/dev/null || echo "Warning: Could not set immutable attribute on .baremetal"
# Update fstab with new UUIDs if any were generated
if [[ ${#uuid_mappings[@]} -gt 0 ]]; then
echo "Updating fstab with new UUIDs..."
# Backup original fstab
sudo cp "$TEMP_MOUNT/etc/fstab" "$TEMP_MOUNT/etc/fstab.backup" || echo "Warning: Could not backup fstab"
# Apply UUID updates to fstab
temp_fstab=$(mktemp)
sudo cp "$TEMP_MOUNT/etc/fstab" "$temp_fstab"
for mapping in "${uuid_mappings[@]}"; do
if [[ "$mapping" =~ ^UUID_MAPPING:([^:]+):([^:]+)$ ]]; then
old_uuid="${BASH_REMATCH[1]}"
new_uuid="${BASH_REMATCH[2]}"
# Replace old UUID with new UUID in fstab
sed -i "s/UUID=$old_uuid/UUID=$new_uuid/g" "$temp_fstab"
echo "Updated fstab: $old_uuid -> $new_uuid"
fi
done
# Copy updated fstab back
sudo cp "$temp_fstab" "$TEMP_MOUNT/etc/fstab"
rm -f "$temp_fstab"
echo "fstab updated successfully"
else
echo "No UUID mappings found - keeping original fstab"
sudo cp "$TEMP_MOUNT/etc/fstab" "$TEMP_MOUNT/etc/fstab.backup" || echo "Warning: Could not backup fstab"
fi
# Also mount and update GRUB config on EFI partition
EFI_MOUNT="/mnt/stormux_efi"
sudo mkdir -p "$EFI_MOUNT"
# Find EFI partition (should be partition 2)
if [[ "$TARGET_DEVICE" =~ (nvme|mmcblk) ]]; then
EFI_PART="${TARGET_DEVICE}p2"
else
EFI_PART="${TARGET_DEVICE}2"
fi
if sudo mount "$EFI_PART" "$EFI_MOUNT" 2>/dev/null; then
echo "Updating GRUB configuration with new UUIDs..."
if [[ -f "$EFI_MOUNT/grub/grub.cfg" && ${#uuid_mappings[@]} -gt 0 ]]; then
# Backup original grub config
sudo cp "$EFI_MOUNT/grub/grub.cfg" "$EFI_MOUNT/grub/grub.cfg.backup" || echo "Warning: Could not backup grub.cfg"
# Apply UUID updates to grub config
grub_temp=$(mktemp)
sudo cp "$EFI_MOUNT/grub/grub.cfg" "$grub_temp"
for mapping in "${uuid_mappings[@]}"; do
if [[ "$mapping" =~ ^UUID_MAPPING:([^:]+):([^:]+)$ ]]; then
grub_old_uuid="${BASH_REMATCH[1]}"
grub_new_uuid="${BASH_REMATCH[2]}"
# Replace old UUID with new UUID in grub config
sed -i "s/${grub_old_uuid}/${grub_new_uuid}/g" "$grub_temp"
echo "Updated grub.cfg: $grub_old_uuid -> $grub_new_uuid"
fi
done
# Copy updated grub config back
sudo cp "$grub_temp" "$EFI_MOUNT/grub/grub.cfg"
rm -f "$grub_temp"
echo "GRUB configuration updated successfully"
else
echo "No GRUB config found or no UUID mappings to update"
fi
sudo umount "$EFI_MOUNT"
else
echo "Warning: Could not mount EFI partition $EFI_PART"
fi
sudo rmdir "$EFI_MOUNT"
# Restore speech
echo "command toggletempdisablespeech" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "Unmounting target partition..."
sudo umount "$TEMP_MOUNT"
else
echo "ERROR: Failed to mount target partition $TARGET_ROOT_PART"
echo "Installation may have failed - please check the target disk"
echo "However, the disk cloning operation completed."
fi fi
log "Root partition mounted successfully"
# Regenerate UUIDs and labels
log "Regenerating partition identifiers..."
mapfile -t uuid_mappings < <(regenerate_partition_identifiers "$TARGET_DEVICE" target_partitions)
log "Generated ${#uuid_mappings[@]} UUID mappings"
# Update fstab with new UUIDs
if ! update_fstab "$TEMP_MOUNT" "${uuid_mappings[@]}"; then
error_exit "Failed to update fstab"
fi
# Create baremetal marker
log "Creating baremetal system marker..."
sudo touch "$TEMP_MOUNT/home/stormux/.baremetal"
sudo chown 1000:1000 "$TEMP_MOUNT/home/stormux/.baremetal" 2>/dev/null || true
sudo chattr +i "$TEMP_MOUNT/home/stormux/.baremetal" 2>/dev/null || log "Warning: Could not set immutable attribute"
# Remove USB-specific markers
sudo rm -f "$TEMP_MOUNT/home/stormux/.firstboot" 2>/dev/null || true
# Install GRUB
if ! install_grub "$TEMP_MOUNT" "$TARGET_DEVICE" target_partitions; then
error_exit "GRUB installation failed"
fi
# Validate installation
if ! validate_installation "$TEMP_MOUNT"; then
error_exit "Installation validation failed"
fi
# Unmount EFI partition if mounted
if [[ -n "${target_partitions[efi]:-}" ]] && mountpoint -q "$TEMP_MOUNT/boot"; then
log "Unmounting EFI partition..."
sudo umount "$TEMP_MOUNT/boot"
fi
# Unmount root partition
log "Unmounting root partition..."
sudo umount "$TEMP_MOUNT"
sudo rmdir "$TEMP_MOUNT" sudo rmdir "$TEMP_MOUNT"
# Success message (using Fenrir auto-restore pattern) # Restore speech
restore_speech
# Success message
log "========================================="
log "Installation completed successfully!"
log "========================================="
echo echo
echo "=========================================" echo "========================================="
echo "Installation completed successfully!" echo "Installation completed successfully!"
echo "The USB system has been cloned to $TARGET_DEVICE" echo "The USB system has been cloned to $TARGET_DEVICE"
echo "You can now reboot and remove the USB drive." echo "You can now reboot and remove the USB drive."
echo "The system will boot from the internal disk." echo "The system will boot from the internal disk."
echo
echo "Log file: $LOGFILE"
echo "=========================================" echo "========================================="
echo echo
echo "Press enter to continue..." echo "Press enter to continue..."