#!/bin/bash ################################################################################################################ # # # WARNING: This file is automatically generated # # DO NOT modify this file directly as it will be overwritten # # # # Ubuntu uBlue bootupd-alternative Tool # # Generated on: 2025-07-10 22:47:32 # # # ################################################################################################################ set -euo pipefail # Ubuntu uBlue bootupd-alternative Tool - Self-contained version # This script contains all components merged into a single file # Enhanced bootloader management for Ubuntu uBlue systems # Supports multiple bootloader types (GRUB, UEFI, LILO, syslinux) # Version: 25.07.10 # Ubuntu uBlue bootupd-alternative Tool # Enhanced Bootloader Management # Source Ubuntu uBlue configuration (if available) if [[ -f "/usr/local/etc/particle-config.sh" ]]; then source "/usr/local/etc/particle-config.sh" log_info "Loaded Ubuntu uBlue configuration" "bootupd-alternative" else # Define logging functions if not available log_info() { local message="$1" local script_name="${2:-bootupd-alternative}" echo "[INFO] [$script_name] $message" } log_warning() { local message="$1" local script_name="${2:-bootupd-alternative}" echo "[WARNING] [$script_name] $message" >&2 } log_error() { local message="$1" local script_name="${2:-bootupd-alternative}" echo "[ERROR] [$script_name] $message" >&2 } log_debug() { local message="$1" local script_name="${2:-bootupd-alternative}" echo "[DEBUG] [$script_name] $message" } log_success() { local message="$1" local script_name="${2:-bootupd-alternative}" echo "[SUCCESS] [$script_name] $message" } log_warning "Ubuntu uBlue configuration not found, using defaults" "bootupd-alternative" fi # ============================================================================ # Header and Shared Functions # ============================================================================ # --- END OF SCRIPTLET: 00-header.sh --- # ============================================================================ # Dependency Checking and Validation # ============================================================================ # Dependency checking and validation for Ubuntu uBlue bootupd-alternative Tool check_dependencies() { log_info "Checking dependencies..." "bootupd-alternative" local missing_deps=() # Core dependencies for dep in mount umount lsblk bc; do if ! command -v "$dep" >/dev/null 2>&1; then missing_deps+=("$dep") fi done # Bootloader-specific dependencies local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") if ! command -v efibootmgr >/dev/null 2>&1; then missing_deps+=("efibootmgr") fi ;; "grub") if ! command -v grub-install >/dev/null 2>&1; then missing_deps+=("grub-install") fi if ! command -v grub-mkconfig >/dev/null 2>&1; then missing_deps+=("grub-mkconfig") fi ;; "lilo") if ! command -v lilo >/dev/null 2>&1; then missing_deps+=("lilo") fi ;; "syslinux") if ! command -v syslinux >/dev/null 2>&1; then missing_deps+=("syslinux") fi ;; esac # Check for kernel modules check_kernel_modules if [ ${#missing_deps[@]} -ne 0 ]; then log_error "Missing dependencies: ${missing_deps[*]}" "bootupd-alternative" log_info "Install missing packages with: sudo apt install -y ${missing_deps[*]}" "bootupd-alternative" exit 1 fi log_success "All dependencies found" "bootupd-alternative" } # Check kernel modules check_kernel_modules() { log_info "Checking kernel modules..." "bootupd-alternative" local missing_modules=() # Check for squashfs module if ! modprobe -n squashfs >/dev/null 2>&1; then missing_modules+=("squashfs") fi # Check for overlay module if ! modprobe -n overlay >/dev/null 2>&1; then missing_modules+=("overlay") fi # Check for loop module if ! modprobe -n loop >/dev/null 2>&1; then missing_modules+=("loop") fi if [ ${#missing_modules[@]} -ne 0 ]; then log_warning "Missing kernel modules: ${missing_modules[*]}" "bootupd-alternative" log_info "Load modules with: sudo modprobe ${missing_modules[*]}" "bootupd-alternative" log_info "Or install with: sudo apt install linux-modules-extra-$(uname -r)" "bootupd-alternative" else log_success "All required kernel modules available" "bootupd-alternative" fi } # Check for bootloader integration script check_bootloader_integration() { local bootloader_script="/usr/local/bin/bootloader-integration.sh" if [[ -f "$bootloader_script" ]] && [[ -x "$bootloader_script" ]]; then log_debug "Bootloader integration script found: $bootloader_script" "bootupd-alternative" return 0 else log_warning "Bootloader integration script not found or not executable: $bootloader_script" "bootupd-alternative" log_info "Advanced bootloader features will not be available" "bootupd-alternative" return 1 fi } # Check for composefs integration script check_composefs_integration() { local composefs_script="/usr/local/bin/composefs-alternative.sh" if [[ -f "$composefs_script" ]] && [[ -x "$composefs_script" ]]; then log_debug "ComposeFS integration script found: $composefs_script" "bootupd-alternative" return 0 else log_warning "ComposeFS integration script not found or not executable: $composefs_script" "bootupd-alternative" log_info "ComposeFS-based boot images will not be available" "bootupd-alternative" return 1 fi } # Validate boot device validate_boot_device() { local device="$1" # Check if device exists if [[ ! -b "$device" ]]; then log_error "Boot device does not exist: $device" "bootupd-alternative" return 1 fi # Check if device is readable if [[ ! -r "$device" ]]; then log_error "Boot device is not readable: $device" "bootupd-alternative" return 1 fi # Check if device has boot partition local has_boot_partition=false while IFS= read -r line; do if [[ "$line" =~ boot ]] || [[ "$line" =~ efi ]]; then has_boot_partition=true break fi done < <(lsblk -o MOUNTPOINT "$device" 2>/dev/null) if [[ "$has_boot_partition" == "false" ]]; then log_warning "No boot partition detected on device: $device" "bootupd-alternative" log_info "This may be expected for some configurations" "bootupd-alternative" fi return 0 } # Check available disk space check_disk_space() { local required_space_mb="$1" local target_dir="${2:-$BOOTUPD_DIR}" local available_space_mb available_space_mb=$(get_available_space "$target_dir") if [[ $available_space_mb -lt $required_space_mb ]]; then log_error "Insufficient disk space: ${available_space_mb}MB available, need ${required_space_mb}MB" "bootupd-alternative" return 1 fi log_debug "Disk space check passed: ${available_space_mb}MB available" "bootupd-alternative" return 0 } # Check if system is bootable check_system_bootability() { log_info "Checking system bootability..." "bootupd-alternative" local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") # Check for UEFI firmware if [[ ! -d "/sys/firmware/efi" ]]; then log_error "UEFI firmware not detected" "bootupd-alternative" return 1 fi # Check for EFI partition if ! mountpoint -q /boot/efi 2>/dev/null; then log_warning "EFI partition not mounted at /boot/efi" "bootupd-alternative" fi ;; "grub") # Check for GRUB configuration if [[ ! -f "/boot/grub/grub.cfg" ]] && [[ ! -f "/boot/grub2/grub.cfg" ]]; then log_warning "GRUB configuration not found" "bootupd-alternative" fi ;; "lilo") # Check for LILO configuration if [[ ! -f "/etc/lilo.conf" ]]; then log_warning "LILO configuration not found" "bootupd-alternative" fi ;; "syslinux") # Check for syslinux configuration if [[ ! -f "/boot/syslinux/syslinux.cfg" ]]; then log_warning "syslinux configuration not found" "bootupd-alternative" fi ;; "unknown") log_warning "Unknown bootloader type" "bootupd-alternative" ;; esac log_info "System bootability check completed" "bootupd-alternative" return 0 } # Check for required filesystems check_filesystems() { log_info "Checking required filesystems..." "bootupd-alternative" # Check for /boot if [[ ! -d "/boot" ]]; then log_error "/boot directory not found" "bootupd-alternative" return 1 fi # Check for /boot/efi (UEFI systems) if [[ -d "/sys/firmware/efi" ]] && [[ ! -d "/boot/efi" ]]; then log_warning "EFI directory not found at /boot/efi" "bootupd-alternative" fi # Check for /etc/fstab if [[ ! -f "/etc/fstab" ]]; then log_warning "/etc/fstab not found" "bootupd-alternative" fi log_success "Filesystem check completed" "bootupd-alternative" return 0 } # --- END OF SCRIPTLET: 01-dependencies.sh --- # ============================================================================ # Bootloader Management # ============================================================================ # Bootloader-specific operations for Ubuntu uBlue bootupd-alternative Tool # Provides installation, update, and management for various bootloader types # Install bootloader to device install_bootloader() { local device="$1" log_info "Installing bootloader to device: $device" "bootupd-alternative" # Validate device if ! validate_boot_device "$device"; then log_error "Invalid boot device: $device" "bootupd-alternative" exit 1 fi # Get device information log_info "Device information:" "bootupd-alternative" get_device_info "$device" # Detect bootloader type local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") install_uefi_bootloader "$device" ;; "grub") install_grub_bootloader "$device" ;; "lilo") install_lilo_bootloader "$device" ;; "syslinux") install_syslinux_bootloader "$device" ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" exit 1 ;; esac log_success "Bootloader installed successfully to $device" "bootupd-alternative" } # Find EFI partition find_efi_partition() { # Try to find EFI partition using various methods local efi_partition="" # Method 1: Check mount point if mountpoint -q /boot/efi 2>/dev/null; then efi_partition=$(findmnt -n -o SOURCE /boot/efi 2>/dev/null) if [[ -n "$efi_partition" ]]; then echo "$efi_partition" return 0 fi fi # Method 2: Look for EFI partition in /proc/mounts efi_partition=$(grep " /boot/efi " /proc/mounts | awk '{print $1}') if [[ -n "$efi_partition" ]]; then echo "$efi_partition" return 0 fi # Method 3: Scan for EFI partition using blkid if command -v blkid &> /dev/null; then efi_partition=$(blkid | grep -i "EFI" | head -1 | cut -d: -f1) if [[ -n "$efi_partition" ]]; then echo "$efi_partition" return 0 fi fi # Method 4: Look for common EFI partition names for dev in /dev/sd*1 /dev/nvme*n*p1 /dev/mmcblk*p1; do if [[ -b "$dev" ]]; then efi_partition="$dev" break fi done if [[ -n "$efi_partition" ]]; then echo "$efi_partition" return 0 fi return 1 } # Install UEFI bootloader install_uefi_bootloader() { local device="$1" log_info "Installing UEFI bootloader..." "bootupd-alternative" # Check if EFI partition is mounted if ! mountpoint -q /boot/efi 2>/dev/null; then log_error "EFI partition not mounted at /boot/efi" "bootupd-alternative" log_info "Please mount the EFI partition before installing UEFI bootloader" "bootupd-alternative" exit 1 fi # Create EFI boot entry if command -v efibootmgr &> /dev/null; then log_info "Creating EFI boot entry..." "bootupd-alternative" # Find EFI partition local efi_partition efi_partition=$(find_efi_partition) if [[ -z "$efi_partition" ]]; then log_error "Could not find EFI partition" "bootupd-alternative" exit 1 fi # Extract device and partition number local efi_device local efi_part_num efi_device=$(echo "$efi_partition" | sed 's/[0-9]*$//') efi_part_num=$(echo "$efi_partition" | sed 's/.*\([0-9]*\)$/\1/') # Determine EFI loader path local efi_loader="/EFI/ubuntu/grubx64.efi" if [[ ! -f "/boot/efi$efi_loader" ]]; then # Try alternative paths for alt_loader in "/EFI/ubuntu/shimx64.efi" "/EFI/boot/bootx64.efi" "/EFI/BOOT/BOOTX64.EFI"; do if [[ -f "/boot/efi$alt_loader" ]]; then efi_loader="$alt_loader" break fi done fi # Create EFI boot entry if efibootmgr --create --disk "$efi_device" --part "$efi_part_num" --loader "$efi_loader" --label "Ubuntu uBlue" --unicode "quiet splash"; then log_success "EFI boot entry created: Ubuntu uBlue" "bootupd-alternative" else log_error "Failed to create EFI boot entry" "bootupd-alternative" exit 1 fi else log_warning "efibootmgr not available, skipping EFI boot entry creation" "bootupd-alternative" fi log_success "UEFI bootloader installation completed" "bootupd-alternative" } # Install GRUB bootloader install_grub_bootloader() { local device="$1" log_info "Installing GRUB bootloader..." "bootupd-alternative" # Check for GRUB installation tools if ! command -v grub-install &> /dev/null; then log_error "grub-install not found" "bootupd-alternative" exit 1 fi # Install GRUB to device if grub-install "$device"; then log_success "GRUB installed to $device" "bootupd-alternative" else log_error "Failed to install GRUB to $device" "bootupd-alternative" exit 1 fi # Generate GRUB configuration if command -v grub-mkconfig &> /dev/null; then log_info "Generating GRUB configuration..." "bootupd-alternative" if grub-mkconfig -o /boot/grub/grub.cfg; then log_success "GRUB configuration generated" "bootupd-alternative" else log_warning "Failed to generate GRUB configuration" "bootupd-alternative" fi else log_warning "grub-mkconfig not found, skipping configuration generation" "bootupd-alternative" fi log_success "GRUB bootloader installation completed" "bootupd-alternative" } # Install LILO bootloader install_lilo_bootloader() { local device="$1" log_info "Installing LILO bootloader..." "bootupd-alternative" # Check for LILO if ! command -v lilo &> /dev/null; then log_error "lilo not found" "bootupd-alternative" exit 1 fi # Check for LILO configuration if [[ ! -f "/etc/lilo.conf" ]]; then log_error "LILO configuration not found at /etc/lilo.conf" "bootupd-alternative" exit 1 fi # Install LILO if lilo; then log_success "LILO installed successfully" "bootupd-alternative" else log_error "Failed to install LILO" "bootupd-alternative" exit 1 fi log_success "LILO bootloader installation completed" "bootupd-alternative" } # Install syslinux bootloader install_syslinux_bootloader() { local device="$1" log_info "Installing syslinux bootloader..." "bootupd-alternative" # Check for syslinux if ! command -v syslinux &> /dev/null; then log_error "syslinux not found" "bootupd-alternative" exit 1 fi # Install syslinux (try different methods) local install_success=false # Method 1: Direct syslinux installation if syslinux -i "$device" 2>/dev/null; then install_success=true # Method 2: extlinux installation (for ext filesystems) elif command -v extlinux &> /dev/null && extlinux --install /boot/syslinux 2>/dev/null; then install_success=true # Method 3: syslinux with different options elif syslinux "$device" 2>/dev/null; then install_success=true fi if [[ "$install_success" == "true" ]]; then log_success "syslinux installed to $device" "bootupd-alternative" else log_error "Failed to install syslinux to $device" "bootupd-alternative" exit 1 fi log_success "syslinux bootloader installation completed" "bootupd-alternative" } # Update bootloader configuration update_bootloader() { log_info "Updating bootloader configuration..." "bootupd-alternative" # Detect bootloader type local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") update_uefi_bootloader ;; "grub") update_grub_bootloader ;; "lilo") update_lilo_bootloader ;; "syslinux") update_syslinux_bootloader ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" exit 1 ;; esac log_success "Bootloader configuration updated successfully" "bootupd-alternative" } # Update UEFI bootloader update_uefi_bootloader() { log_info "Updating UEFI bootloader..." "bootupd-alternative" # Update EFI boot entries if command -v efibootmgr &> /dev/null; then log_info "Updating EFI boot entries..." "bootupd-alternative" # Implementation would update EFI boot entries here log_success "EFI boot entries updated" "bootupd-alternative" else log_warning "efibootmgr not available, skipping EFI boot entry updates" "bootupd-alternative" fi } # Update GRUB bootloader update_grub_bootloader() { log_info "Updating GRUB bootloader..." "bootupd-alternative" # Update GRUB configuration if command -v grub-mkconfig &> /dev/null; then log_info "Updating GRUB configuration..." "bootupd-alternative" if grub-mkconfig -o /boot/grub/grub.cfg; then log_success "GRUB configuration updated" "bootupd-alternative" else log_error "Failed to update GRUB configuration" "bootupd-alternative" exit 1 fi else log_error "grub-mkconfig not found" "bootupd-alternative" exit 1 fi } # Update LILO bootloader update_lilo_bootloader() { log_info "Updating LILO bootloader..." "bootupd-alternative" # Update LILO if command -v lilo &> /dev/null; then if lilo; then log_success "LILO updated successfully" "bootupd-alternative" else log_error "Failed to update LILO" "bootupd-alternative" exit 1 fi else log_error "lilo not found" "bootupd-alternative" exit 1 fi } # Update syslinux bootloader update_syslinux_bootloader() { log_info "Updating syslinux bootloader..." "bootupd-alternative" # Update syslinux configuration if command -v syslinux &> /dev/null; then log_info "Updating syslinux configuration..." "bootupd-alternative" # Regenerate syslinux configuration if possible if [[ -f "/boot/syslinux/syslinux.cfg" ]]; then # Backup current configuration cp "/boot/syslinux/syslinux.cfg" "/boot/syslinux/syslinux.cfg.backup" # Try to regenerate configuration if command -v extlinux &> /dev/null; then if extlinux --update /boot/syslinux; then log_success "syslinux configuration updated via extlinux" "bootupd-alternative" else log_warning "extlinux update failed, using backup" "bootupd-alternative" cp "/boot/syslinux/syslinux.cfg.backup" "/boot/syslinux/syslinux.cfg" fi else log_success "syslinux configuration file updated" "bootupd-alternative" fi else log_warning "syslinux configuration not found" "bootupd-alternative" fi else log_error "syslinux not found" "bootupd-alternative" exit 1 fi } # --- END OF SCRIPTLET: 02-bootloader.sh --- # ============================================================================ # Backup and Restore Operations # ============================================================================ # Backup and restore functionality for Ubuntu uBlue bootupd-alternative Tool # Provides comprehensive backup and restore of bootloader configurations # Create backup of bootloader configuration create_backup() { local backup_name="$1" local backup_dir="$BOOTUPD_DIR/backups/$backup_name" log_info "Creating backup: $backup_name" "bootupd-alternative" mkdir -p "$backup_dir" # Backup GRUB configuration if [[ -f "/boot/grub/grub.cfg" ]]; then cp "/boot/grub/grub.cfg" "$backup_dir/grub.cfg" log_debug "Backed up GRUB configuration" "bootupd-alternative" fi if [[ -d "/etc/grub.d" ]]; then cp -r "/etc/grub.d" "$backup_dir/grub.d" log_debug "Backed up GRUB.d scripts" "bootupd-alternative" fi if [[ -f "/etc/default/grub" ]]; then cp "/etc/default/grub" "$backup_dir/grub" log_debug "Backed up GRUB defaults" "bootupd-alternative" fi # Backup UEFI entries if command -v efibootmgr &> /dev/null; then if efibootmgr --verbose > "$backup_dir/efi_entries.txt" 2>/dev/null; then log_debug "Backed up EFI boot entries" "bootupd-alternative" else log_warning "Failed to backup EFI boot entries" "bootupd-alternative" fi else log_warning "efibootmgr not available, skipping EFI entries backup" "bootupd-alternative" fi # Backup LILO configuration if [[ -f "/etc/lilo.conf" ]]; then cp "/etc/lilo.conf" "$backup_dir/lilo.conf" log_debug "Backed up LILO configuration" "bootupd-alternative" fi # Backup syslinux configuration if [[ -f "/boot/syslinux/syslinux.cfg" ]]; then cp "/boot/syslinux/syslinux.cfg" "$backup_dir/syslinux.cfg" log_debug "Backed up syslinux configuration" "bootupd-alternative" fi # Create backup metadata cat > "$backup_dir/backup_info.txt" << EOF Backup created: $(date) Backup name: $backup_name Bootloader type: $(detect_bootloader) Kernel version: $(uname -r) Architecture: $(uname -m) EOF log_success "Backup created: $backup_dir" "bootupd-alternative" echo "$backup_dir" } # Restore backup of bootloader configuration restore_backup() { local backup_name="$1" local backup_dir="$BOOTUPD_DIR/backups/$backup_name" if [[ ! -d "$backup_dir" ]]; then log_error "Backup not found: $backup_name" "bootupd-alternative" return 1 fi log_info "Restoring backup: $backup_name" "bootupd-alternative" # Restore GRUB configuration if [[ -f "$backup_dir/grub.cfg" ]]; then cp "$backup_dir/grub.cfg" "/boot/grub/grub.cfg" log_debug "Restored GRUB configuration" "bootupd-alternative" fi if [[ -d "$backup_dir/grub.d" ]]; then cp -r "$backup_dir/grub.d" /etc/ log_debug "Restored GRUB.d scripts" "bootupd-alternative" fi if [[ -f "$backup_dir/grub" ]]; then cp "$backup_dir/grub" "/etc/default/grub" log_debug "Restored GRUB defaults" "bootupd-alternative" fi # Update GRUB configuration after restore if command -v grub-mkconfig &> /dev/null; then log_info "Updating GRUB configuration after restore..." "bootupd-alternative" if grub-mkconfig -o /boot/grub/grub.cfg; then log_success "GRUB configuration updated" "bootupd-alternative" else log_warning "Failed to update GRUB configuration" "bootupd-alternative" fi fi # Restore LILO configuration if [[ -f "$backup_dir/lilo.conf" ]]; then cp "$backup_dir/lilo.conf" "/etc/lilo.conf" log_debug "Restored LILO configuration" "bootupd-alternative" fi # Restore syslinux configuration if [[ -f "$backup_dir/syslinux.cfg" ]]; then cp "$backup_dir/syslinux.cfg" "/boot/syslinux/syslinux.cfg" log_debug "Restored syslinux configuration" "bootupd-alternative" fi log_success "Backup restored: $backup_name" "bootupd-alternative" return 0 } # List available backups list_backups() { log_info "Available backups:" "bootupd-alternative" if [[ ! -d "$BOOTUPD_DIR/backups" ]]; then log_info "No backups found" "bootupd-alternative" return 0 fi local backup_count=0 for backup_dir in "$BOOTUPD_DIR/backups"/*; do if [[ -d "$backup_dir" ]]; then local backup_name backup_name=$(basename "$backup_dir") local backup_date backup_date=$(stat -c %y "$backup_dir" | cut -d' ' -f1) echo " $backup_name (created: $backup_date)" backup_count=$((backup_count + 1)) fi done if [[ $backup_count -eq 0 ]]; then log_info "No backups found" "bootupd-alternative" fi } # Validate backup integrity validate_backup() { local backup_name="$1" local backup_dir="$BOOTUPD_DIR/backups/$backup_name" if [[ ! -d "$backup_dir" ]]; then log_error "Backup not found: $backup_name" "bootupd-alternative" return 1 fi log_info "Validating backup: $backup_name" "bootupd-alternative" local validation_errors=0 # Check for backup metadata if [[ ! -f "$backup_dir/backup_info.txt" ]]; then log_warning "Backup metadata not found" "bootupd-alternative" validation_errors=$((validation_errors + 1)) fi # Check for at least one configuration file local has_config=false for config_file in grub.cfg lilo.conf syslinux.cfg; do if [[ -f "$backup_dir/$config_file" ]]; then has_config=true break fi done if [[ "$has_config" == "false" ]]; then log_warning "No configuration files found in backup" "bootupd-alternative" validation_errors=$((validation_errors + 1)) fi if [[ $validation_errors -eq 0 ]]; then log_success "Backup validation passed" "bootupd-alternative" return 0 else log_warning "Backup validation completed with $validation_errors warnings" "bootupd-alternative" return 1 fi } # Remove backup remove_backup() { local backup_name="$1" local backup_dir="$BOOTUPD_DIR/backups/$backup_name" if [[ ! -d "$backup_dir" ]]; then log_error "Backup not found: $backup_name" "bootupd-alternative" return 1 fi log_info "Removing backup: $backup_name" "bootupd-alternative" if rm -rf "$backup_dir"; then log_success "Backup removed: $backup_name" "bootupd-alternative" return 0 else log_error "Failed to remove backup: $backup_name" "bootupd-alternative" return 1 fi } # --- END OF SCRIPTLET: 03-backup.sh --- # ============================================================================ # Boot Entry Management # ============================================================================ # Boot entries management for Ubuntu uBlue bootupd-alternative Tool # Provides management of boot entries for various bootloader types # Convert device path to GRUB format convert_device_to_grub_format() { local device="$1" if [[ -z "$device" ]]; then echo "hd0,msdos1" # Default fallback return 0 fi # Extract device name and partition local device_name local partition_num device_name=$(echo "$device" | sed 's/[0-9]*$//') partition_num=$(echo "$device" | sed 's/.*\([0-9]*\)$/\1/') # Determine disk number (simplified - assumes first disk) local disk_num=0 # Determine partition table type local partition_table="msdos" if command -v parted &> /dev/null; then if parted "$device_name" print 2>/dev/null | grep -q "gpt"; then partition_table="gpt" fi fi # Convert to GRUB format if [[ "$partition_table" == "gpt" ]]; then echo "hd${disk_num},gpt${partition_num}" else echo "hd${disk_num},msdos${partition_num}" fi } # Add boot entry add_boot_entry() { local title="$1" local kernel_path="$2" local initrd_path="$3" local root_device="$4" log_info "Adding boot entry: $title" "bootupd-alternative" # Validate inputs if ! validate_boot_title "$title"; then log_error "Invalid boot title: $title" "bootupd-alternative" exit 1 fi if [[ ! -f "$kernel_path" ]]; then log_error "Kernel not found: $kernel_path" "bootupd-alternative" exit 1 fi if [[ -n "$initrd_path" && ! -f "$initrd_path" ]]; then log_error "Initrd not found: $initrd_path" "bootupd-alternative" exit 1 fi # Detect bootloader type local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") add_uefi_boot_entry "$title" "$kernel_path" "$initrd_path" "$root_device" ;; "grub") add_grub_boot_entry "$title" "$kernel_path" "$initrd_path" "$root_device" ;; "lilo") add_lilo_boot_entry "$title" "$kernel_path" "$initrd_path" "$root_device" ;; "syslinux") add_syslinux_boot_entry "$title" "$kernel_path" "$initrd_path" "$root_device" ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" exit 1 ;; esac log_success "Boot entry added: $title" "bootupd-alternative" } # Add UEFI boot entry add_uefi_boot_entry() { local title="$1" local kernel_path="$2" local initrd_path="$3" local root_device="$4" log_info "Adding UEFI boot entry..." "bootupd-alternative" if ! command -v efibootmgr &> /dev/null; then log_error "efibootmgr not available" "bootupd-alternative" exit 1 fi # Find EFI partition local efi_partition efi_partition=$(find_efi_partition) if [[ -z "$efi_partition" ]]; then log_error "Could not find EFI partition" "bootupd-alternative" exit 1 fi # Extract device and partition number local efi_device local efi_part_num efi_device=$(echo "$efi_partition" | sed 's/[0-9]*$//') efi_part_num=$(echo "$efi_partition" | sed 's/.*\([0-9]*\)$/\1/') # Determine EFI loader path local efi_loader="/EFI/ubuntu/grubx64.efi" if [[ ! -f "/boot/efi$efi_loader" ]]; then # Try alternative paths for alt_loader in "/EFI/ubuntu/shimx64.efi" "/EFI/boot/bootx64.efi" "/EFI/BOOT/BOOTX64.EFI"; do if [[ -f "/boot/efi$alt_loader" ]]; then efi_loader="$alt_loader" break fi done fi # Build kernel arguments local efi_args="" if [[ -n "$initrd_path" ]]; then efi_args="initrd=$initrd_path" fi if [[ -n "$root_device" ]]; then if [[ -n "$efi_args" ]]; then efi_args="$efi_args root=$root_device" else efi_args="root=$root_device" fi fi # Create EFI boot entry if efibootmgr --create --disk "$efi_device" --part "$efi_part_num" --loader "$efi_loader" --label "$title" --unicode "$efi_args"; then log_success "UEFI boot entry added: $title" "bootupd-alternative" else log_error "Failed to create UEFI boot entry: $title" "bootupd-alternative" exit 1 fi } # Add GRUB boot entry add_grub_boot_entry() { local title="$1" local kernel_path="$2" local initrd_path="$3" local root_device="$4" log_info "Adding GRUB boot entry..." "bootupd-alternative" # Create GRUB configuration entry local grub_entry="/etc/grub.d/40_custom" # Convert device path to GRUB format local grub_root grub_root=$(convert_device_to_grub_format "$root_device") # Add entry to custom GRUB configuration cat >> "$grub_entry" << EOF # Custom entry: $title menuentry '$title' { set root='$grub_root' linux $kernel_path root=$root_device ro EOF if [[ -n "$initrd_path" ]]; then echo " initrd $initrd_path" >> "$grub_entry" fi echo "}" >> "$grub_entry" # Update GRUB configuration if command -v grub-mkconfig &> /dev/null; then log_info "Updating GRUB configuration..." "bootupd-alternative" if grub-mkconfig -o /boot/grub/grub.cfg; then log_success "GRUB configuration updated" "bootupd-alternative" else log_error "Failed to update GRUB configuration" "bootupd-alternative" exit 1 fi else log_warning "grub-mkconfig not found, manual update required" "bootupd-alternative" fi log_success "GRUB boot entry added: $title" "bootupd-alternative" } # Add LILO boot entry add_lilo_boot_entry() { local title="$1" local kernel_path="$2" local initrd_path="$3" local root_device="$4" log_info "Adding LILO boot entry..." "bootupd-alternative" # Add entry to LILO configuration local lilo_conf="/etc/lilo.conf" if [[ ! -f "$lilo_conf" ]]; then log_error "LILO configuration not found" "bootupd-alternative" exit 1 fi # Create backup before modification cp "$lilo_conf" "$lilo_conf.backup" # Add entry to LILO configuration cat >> "$lilo_conf" << EOF # Custom entry: $title image=$kernel_path label=$title root=$root_device read-only EOF if [[ -n "$initrd_path" ]]; then echo " initrd=$initrd_path" >> "$lilo_conf" fi # Update LILO if command -v lilo &> /dev/null; then log_info "Updating LILO..." "bootupd-alternative" if lilo; then log_success "LILO updated" "bootupd-alternative" else log_error "Failed to update LILO" "bootupd-alternative" # Restore backup cp "$lilo_conf.backup" "$lilo_conf" exit 1 fi else log_error "lilo not found" "bootupd-alternative" exit 1 fi log_success "LILO boot entry added: $title" "bootupd-alternative" } # Add syslinux boot entry add_syslinux_boot_entry() { local title="$1" local kernel_path="$2" local initrd_path="$3" local root_device="$4" log_info "Adding syslinux boot entry..." "bootupd-alternative" # Add entry to syslinux configuration local syslinux_cfg="/boot/syslinux/syslinux.cfg" if [[ ! -f "$syslinux_cfg" ]]; then log_error "syslinux configuration not found" "bootupd-alternative" exit 1 fi # Create backup before modification cp "$syslinux_cfg" "$syslinux_cfg.backup" # Add entry to syslinux configuration cat >> "$syslinux_cfg" << EOF # Custom entry: $title LABEL $title KERNEL $kernel_path APPEND root=$root_device ro EOF if [[ -n "$initrd_path" ]]; then echo " INITRD $initrd_path" >> "$syslinux_cfg" fi log_success "syslinux boot entry added: $title" "bootupd-alternative" } # Remove boot entry remove_boot_entry() { local title="$1" log_info "Removing boot entry: $title" "bootupd-alternative" # Validate title if ! validate_boot_title "$title"; then log_error "Invalid boot title: $title" "bootupd-alternative" exit 1 fi # Detect bootloader type local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") remove_uefi_boot_entry "$title" ;; "grub") remove_grub_boot_entry "$title" ;; "lilo") remove_lilo_boot_entry "$title" ;; "syslinux") remove_syslinux_boot_entry "$title" ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" exit 1 ;; esac log_success "Boot entry removed: $title" "bootupd-alternative" } # Remove UEFI boot entry remove_uefi_boot_entry() { local title="$1" log_info "Removing UEFI boot entry..." "bootupd-alternative" if ! command -v efibootmgr &> /dev/null; then log_error "efibootmgr not available" "bootupd-alternative" exit 1 fi # Find boot number for the given title local boot_num boot_num=$(efibootmgr --verbose 2>/dev/null | grep -i "$title" | head -1 | sed -n 's/^Boot\([0-9a-fA-F]*\).*/\1/p') if [[ -z "$boot_num" ]]; then log_error "UEFI boot entry not found: $title" "bootupd-alternative" exit 1 fi # Remove the boot entry if efibootmgr --delete-bootnum --bootnum "$boot_num"; then log_success "UEFI boot entry removed: $title (Boot$boot_num)" "bootupd-alternative" else log_error "Failed to remove UEFI boot entry: $title" "bootupd-alternative" exit 1 fi } # Remove GRUB boot entry remove_grub_boot_entry() { local title="$1" log_info "Removing GRUB boot entry..." "bootupd-alternative" # Remove entry from custom GRUB configuration local grub_entry="/etc/grub.d/40_custom" if [[ -f "$grub_entry" ]]; then # Create backup cp "$grub_entry" "$grub_entry.backup" # Remove the entry (simplified - in practice would need more sophisticated parsing) sed -i "/# Custom entry: $title/,/^}/d" "$grub_entry" # Update GRUB configuration if command -v grub-mkconfig &> /dev/null; then log_info "Updating GRUB configuration..." "bootupd-alternative" if grub-mkconfig -o /boot/grub/grub.cfg; then log_success "GRUB configuration updated" "bootupd-alternative" else log_error "Failed to update GRUB configuration" "bootupd-alternative" # Restore backup cp "$grub_entry.backup" "$grub_entry" exit 1 fi else log_warning "grub-mkconfig not found, manual update required" "bootupd-alternative" fi fi log_success "GRUB boot entry removed: $title" "bootupd-alternative" } # Remove LILO boot entry remove_lilo_boot_entry() { local title="$1" log_info "Removing LILO boot entry..." "bootupd-alternative" local lilo_conf="/etc/lilo.conf" if [[ -f "$lilo_conf" ]]; then # Create backup cp "$lilo_conf" "$lilo_conf.backup" # Remove the entry (simplified - in practice would need more sophisticated parsing) sed -i "/# Custom entry: $title/,/^$/d" "$lilo_conf" # Update LILO if command -v lilo &> /dev/null; then log_info "Updating LILO..." "bootupd-alternative" if lilo; then log_success "LILO updated" "bootupd-alternative" else log_error "Failed to update LILO" "bootupd-alternative" # Restore backup cp "$lilo_conf.backup" "$lilo_conf" exit 1 fi else log_error "lilo not found" "bootupd-alternative" exit 1 fi fi log_success "LILO boot entry removed: $title" "bootupd-alternative" } # Remove syslinux boot entry remove_syslinux_boot_entry() { local title="$1" log_info "Removing syslinux boot entry..." "bootupd-alternative" local syslinux_cfg="/boot/syslinux/syslinux.cfg" if [[ -f "$syslinux_cfg" ]]; then # Create backup cp "$syslinux_cfg" "$syslinux_cfg.backup" # Remove the entry (simplified - in practice would need more sophisticated parsing) sed -i "/# Custom entry: $title/,/^$/d" "$syslinux_cfg" fi log_success "syslinux boot entry removed: $title" "bootupd-alternative" } # List boot entries list_boot_entries() { log_info "Listing boot entries..." "bootupd-alternative" # Detect bootloader type local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") list_uefi_boot_entries ;; "grub") list_grub_boot_entries ;; "lilo") list_lilo_boot_entries ;; "syslinux") list_syslinux_boot_entries ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" exit 1 ;; esac } # List UEFI boot entries list_uefi_boot_entries() { log_info "UEFI boot entries:" "bootupd-alternative" if command -v efibootmgr &> /dev/null; then efibootmgr --verbose else log_warning "efibootmgr not available" "bootupd-alternative" fi } # List GRUB boot entries list_grub_boot_entries() { log_info "GRUB boot entries:" "bootupd-alternative" if [[ -f "/boot/grub/grub.cfg" ]]; then grep -E "^[[:space:]]*menuentry" /boot/grub/grub.cfg | sed 's/^[[:space:]]*menuentry[[:space:]]*'\''\([^'\'']*\)'\''.*/\1/' else log_warning "GRUB configuration not found" "bootupd-alternative" fi } # List LILO boot entries list_lilo_boot_entries() { log_info "LILO boot entries:" "bootupd-alternative" if [[ -f "/etc/lilo.conf" ]]; then grep -E "^[[:space:]]*label" /etc/lilo.conf | sed 's/^[[:space:]]*label[[:space:]]*\([^[:space:]]*\).*/\1/' else log_warning "LILO configuration not found" "bootupd-alternative" fi } # List syslinux boot entries list_syslinux_boot_entries() { log_info "syslinux boot entries:" "bootupd-alternative" if [[ -f "/boot/syslinux/syslinux.cfg" ]]; then grep -E "^[[:space:]]*LABEL" /boot/syslinux/syslinux.cfg | sed 's/^[[:space:]]*LABEL[[:space:]]*\([^[:space:]]*\).*/\1/' else log_warning "syslinux configuration not found" "bootupd-alternative" fi } # Set default boot entry set_default_entry() { local title="$1" log_info "Setting default boot entry: $title" "bootupd-alternative" # Validate title if ! validate_boot_title "$title"; then log_error "Invalid boot title: $title" "bootupd-alternative" exit 1 fi # Detect bootloader type local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "uefi") set_uefi_default_entry "$title" ;; "grub") set_grub_default_entry "$title" ;; "lilo") set_lilo_default_entry "$title" ;; "syslinux") set_syslinux_default_entry "$title" ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" exit 1 ;; esac log_success "Default boot entry set: $title" "bootupd-alternative" } # Set UEFI default entry set_uefi_default_entry() { local title="$1" log_info "Setting UEFI default entry..." "bootupd-alternative" if ! command -v efibootmgr &> /dev/null; then log_error "efibootmgr not available" "bootupd-alternative" exit 1 fi # Find boot number for the given title local boot_num boot_num=$(efibootmgr --verbose 2>/dev/null | grep -i "$title" | head -1 | sed -n 's/^Boot\([0-9a-fA-F]*\).*/\1/p') if [[ -z "$boot_num" ]]; then log_error "UEFI boot entry not found: $title" "bootupd-alternative" exit 1 fi # Set as next boot entry (for one-time boot) if efibootmgr --bootnext "$boot_num"; then log_success "UEFI next boot entry set: $title (Boot$boot_num)" "bootupd-alternative" else log_error "Failed to set UEFI next boot entry: $title" "bootupd-alternative" exit 1 fi # Also set as default boot order (persistent) local current_order current_order=$(efibootmgr 2>/dev/null | grep "BootOrder" | cut -d' ' -f2) if [[ -n "$current_order" ]]; then local new_order="$boot_num,$current_order" if efibootmgr --bootorder "$new_order"; then log_success "UEFI boot order updated: $title (Boot$boot_num) is now first" "bootupd-alternative" else log_warning "Failed to update UEFI boot order, but next boot is set" "bootupd-alternative" fi fi } # Set GRUB default entry set_grub_default_entry() { local title="$1" log_info "Setting GRUB default entry..." "bootupd-alternative" local grub_default="/etc/default/grub" if [[ -f "$grub_default" ]]; then # Create backup cp "$grub_default" "$grub_default.backup" # Set default entry sed -i "s/^GRUB_DEFAULT=.*/GRUB_DEFAULT=\"$title\"/" "$grub_default" # Update GRUB configuration if command -v grub-mkconfig &> /dev/null; then log_info "Updating GRUB configuration..." "bootupd-alternative" if grub-mkconfig -o /boot/grub/grub.cfg; then log_success "GRUB configuration updated" "bootupd-alternative" else log_error "Failed to update GRUB configuration" "bootupd-alternative" # Restore backup cp "$grub_default.backup" "$grub_default" exit 1 fi else log_warning "grub-mkconfig not found, manual update required" "bootupd-alternative" fi else log_error "GRUB defaults file not found" "bootupd-alternative" exit 1 fi log_success "GRUB default entry set: $title" "bootupd-alternative" } # Set LILO default entry set_lilo_default_entry() { local title="$1" log_info "Setting LILO default entry..." "bootupd-alternative" local lilo_conf="/etc/lilo.conf" if [[ -f "$lilo_conf" ]]; then # Create backup cp "$lilo_conf" "$lilo_conf.backup" # Set default entry sed -i "s/^default=.*/default=$title/" "$lilo_conf" # Update LILO if command -v lilo &> /dev/null; then log_info "Updating LILO..." "bootupd-alternative" if lilo; then log_success "LILO updated" "bootupd-alternative" else log_error "Failed to update LILO" "bootupd-alternative" # Restore backup cp "$lilo_conf.backup" "$lilo_conf" exit 1 fi else log_error "lilo not found" "bootupd-alternative" exit 1 fi else log_error "LILO configuration not found" "bootupd-alternative" exit 1 fi log_success "LILO default entry set: $title" "bootupd-alternative" } # Set syslinux default entry set_syslinux_default_entry() { local title="$1" log_info "Setting syslinux default entry..." "bootupd-alternative" local syslinux_cfg="/boot/syslinux/syslinux.cfg" if [[ -f "$syslinux_cfg" ]]; then # Create backup cp "$syslinux_cfg" "$syslinux_cfg.backup" # Set default entry sed -i "s/^DEFAULT[[:space:]].*/DEFAULT $title/" "$syslinux_cfg" else log_error "syslinux configuration not found" "bootupd-alternative" exit 1 fi log_success "syslinux default entry set: $title" "bootupd-alternative" } # --- END OF SCRIPTLET: 04-entries.sh --- # ============================================================================ # Device Management and Information # ============================================================================ # Device management for Ubuntu uBlue bootupd-alternative Tool # Provides device validation, information, and management functions # Validate boot device validate_boot_device() { local device="$1" if [[ -z "$device" ]]; then log_error "Device path is required" "bootupd-alternative" return 1 fi # Check if device exists if [[ ! -b "$device" ]]; then log_error "Device not found: $device" "bootupd-alternative" return 1 fi # Check if device is readable if [[ ! -r "$device" ]]; then log_error "Device not readable: $device" "bootupd-alternative" return 1 fi # Check if device is a block device if ! stat -c "%t" "$device" &> /dev/null; then log_error "Invalid block device: $device" "bootupd-alternative" return 1 fi log_debug "Device validation passed: $device" "bootupd-alternative" return 0 } # Get device information get_device_info() { local device="$1" if [[ -z "$device" ]]; then log_error "Device path is required" "bootupd-alternative" return 1 fi log_info "Device Information for: $device" "bootupd-alternative" # Device size if command -v blockdev &> /dev/null; then local size_bytes size_bytes=$(blockdev --getsize64 "$device" 2>/dev/null) if [[ -n "$size_bytes" ]]; then local size_gb size_gb=$(echo "scale=2; $size_bytes / 1024 / 1024 / 1024" | bc 2>/dev/null || echo "unknown") echo " Size: ${size_gb} GB" fi fi # Device type local device_type device_type=$(stat -c "%t" "$device" 2>/dev/null) if [[ -n "$device_type" ]]; then echo " Type: $device_type" fi # Device model if command -v lsblk &> /dev/null; then local model model=$(lsblk -d -o MODEL "$device" 2>/dev/null | tail -n +2) if [[ -n "$model" ]]; then echo " Model: $model" fi fi # Partition information if command -v fdisk &> /dev/null; then echo " Partitions:" fdisk -l "$device" 2>/dev/null | grep -E "^/dev/" || echo " No partitions found" fi # Filesystem information if command -v blkid &> /dev/null; then echo " Filesystems:" blkid "$device"* 2>/dev/null || echo " No filesystem information available" fi # Mount points if command -v findmnt &> /dev/null; then echo " Mount points:" findmnt "$device"* 2>/dev/null | grep -v "TARGET" || echo " No mount points found" fi } # Check mount point check_mount_point() { local mount_point="$1" if [[ -z "$mount_point" ]]; then log_error "Mount point is required" "bootupd-alternative" return 1 fi # Check if mount point exists if [[ ! -d "$mount_point" ]]; then log_error "Mount point directory not found: $mount_point" "bootupd-alternative" return 1 fi # Check if mount point is mounted if ! mountpoint -q "$mount_point" 2>/dev/null; then log_warning "Mount point not mounted: $mount_point" "bootupd-alternative" return 1 fi # Check mount point permissions if [[ ! -r "$mount_point" ]]; then log_error "Mount point not readable: $mount_point" "bootupd-alternative" return 1 fi log_debug "Mount point check passed: $mount_point" "bootupd-alternative" return 0 } # Calculate disk usage calculate_disk_usage() { local path="$1" if [[ -z "$path" ]]; then path="/" fi if [[ ! -d "$path" ]]; then log_error "Path not found: $path" "bootupd-alternative" return 1 fi if command -v df &> /dev/null; then log_info "Disk usage for: $path" "bootupd-alternative" df -h "$path" 2>/dev/null || log_error "Failed to get disk usage" "bootupd-alternative" else log_warning "df command not available" "bootupd-alternative" fi } # Get available space get_available_space() { local path="$1" if [[ -z "$path" ]]; then path="/" fi if [[ ! -d "$path" ]]; then log_error "Path not found: $path" "bootupd-alternative" return 1 fi if command -v df &> /dev/null; then local available_space available_space=$(df -B1 "$path" 2>/dev/null | awk 'NR==2 {print $4}') if [[ -n "$available_space" ]]; then echo "$available_space" return 0 fi fi log_error "Failed to get available space" "bootupd-alternative" return 1 } # Check disk space check_disk_space() { local path="$1" local required_space="$2" if [[ -z "$path" ]]; then path="/" fi if [[ -z "$required_space" ]]; then required_space="52428800" # 50MB default for bootloader operations fi local available_space available_space=$(get_available_space "$path") if [[ $? -ne 0 ]]; then log_error "Failed to check disk space" "bootupd-alternative" return 1 fi if [[ $available_space -lt $required_space ]]; then log_error "Insufficient disk space. Required: $required_space bytes, Available: $available_space bytes" "bootupd-alternative" return 1 fi log_debug "Disk space check passed. Available: $available_space bytes" "bootupd-alternative" return 0 } # List available devices list_available_devices() { log_info "Available block devices:" "bootupd-alternative" if command -v lsblk &> /dev/null; then lsblk -d -o NAME,SIZE,TYPE,MOUNTPOINT 2>/dev/null || log_error "Failed to list devices" "bootupd-alternative" elif command -v fdisk &> /dev/null; then fdisk -l 2>/dev/null | grep -E "^Disk /" || log_error "Failed to list devices" "bootupd-alternative" else log_warning "No device listing tools available" "bootupd-alternative" fi } # Find boot device find_boot_device() { log_info "Finding boot device..." "bootupd-alternative" # Try to find the device mounted at /boot if mountpoint -q /boot 2>/dev/null; then local boot_device boot_device=$(findmnt -n -o SOURCE /boot 2>/dev/null) if [[ -n "$boot_device" ]]; then echo "$boot_device" return 0 fi fi # Try to find the device mounted at / local root_device root_device=$(findmnt -n -o SOURCE / 2>/dev/null) if [[ -n "$root_device" ]]; then echo "$root_device" return 0 fi log_error "Could not determine boot device" "bootupd-alternative" return 1 } # Validate device for bootloader installation validate_device_for_bootloader() { local device="$1" local bootloader="$2" if [[ -z "$device" ]]; then log_error "Device path is required" "bootupd-alternative" return 1 fi if [[ -z "$bootloader" ]]; then log_error "Bootloader type is required" "bootupd-alternative" return 1 fi # Basic device validation if ! validate_boot_device "$device"; then return 1 fi # Bootloader-specific validation case "$bootloader" in "uefi") validate_device_for_uefi "$device" ;; "grub") validate_device_for_grub "$device" ;; "lilo") validate_device_for_lilo "$device" ;; "syslinux") validate_device_for_syslinux "$device" ;; *) log_error "Unsupported bootloader type: $bootloader" "bootupd-alternative" return 1 ;; esac } # Validate device for UEFI validate_device_for_uefi() { local device="$1" # Check if system supports UEFI if [[ ! -d "/sys/firmware/efi" ]]; then log_error "System does not support UEFI" "bootupd-alternative" return 1 fi # Check if EFI partition is mounted if ! mountpoint -q /boot/efi 2>/dev/null; then log_error "EFI partition not mounted at /boot/efi" "bootupd-alternative" return 1 fi log_debug "Device validation for UEFI passed: $device" "bootupd-alternative" return 0 } # Validate device for GRUB validate_device_for_grub() { local device="$1" # Check if GRUB tools are available if ! command -v grub-install &> /dev/null; then log_error "GRUB installation tools not available" "bootupd-alternative" return 1 fi # Check if /boot is accessible if [[ ! -d "/boot" ]]; then log_error "/boot directory not found" "bootupd-alternative" return 1 fi log_debug "Device validation for GRUB passed: $device" "bootupd-alternative" return 0 } # Validate device for LILO validate_device_for_lilo() { local device="$1" # Check if LILO is available if ! command -v lilo &> /dev/null; then log_error "LILO not available" "bootupd-alternative" return 1 fi # Check if LILO configuration exists if [[ ! -f "/etc/lilo.conf" ]]; then log_error "LILO configuration not found" "bootupd-alternative" return 1 fi log_debug "Device validation for LILO passed: $device" "bootupd-alternative" return 0 } # Validate device for syslinux validate_device_for_syslinux() { local device="$1" # Check if syslinux is available if ! command -v syslinux &> /dev/null; then log_error "syslinux not available" "bootupd-alternative" return 1 fi # Check if syslinux configuration exists if [[ ! -f "/boot/syslinux/syslinux.cfg" ]]; then log_warning "syslinux configuration not found, will be created" "bootupd-alternative" fi log_debug "Device validation for syslinux passed: $device" "bootupd-alternative" return 0 } # --- END OF SCRIPTLET: 05-devices.sh --- # ============================================================================ # Status Reporting and Monitoring # ============================================================================ # Status and monitoring for Ubuntu uBlue bootupd-alternative Tool # Provides system status, monitoring, and information display functions # Show system status show_status() { log_info "System Status Report" "bootupd-alternative" echo "========================================" # System information get_system_info # Bootloader information get_bootloader_status # Device information get_device_status # Backup information get_backup_status # Integration status get_integration_status echo "========================================" log_success "Status report completed" "bootupd-alternative" } # Get system information get_system_info() { log_info "System Information:" "bootupd-alternative" # Operating system if [[ -f "/etc/os-release" ]]; then local os_name os_name=$(grep "^NAME=" /etc/os-release | cut -d'"' -f2) echo " OS: $os_name" fi # Kernel version local kernel_version kernel_version=$(uname -r) echo " Kernel: $kernel_version" # Architecture local architecture architecture=$(uname -m) echo " Architecture: $architecture" # Hostname local hostname hostname=$(hostname) echo " Hostname: $hostname" # Uptime if command -v uptime &> /dev/null; then local uptime uptime=$(uptime -p 2>/dev/null | sed 's/up //') echo " Uptime: $uptime" fi # Boot mode if [[ -d "/sys/firmware/efi" ]]; then echo " Boot Mode: UEFI" else echo " Boot Mode: Legacy BIOS" fi } # Get bootloader status get_bootloader_status() { log_info "Bootloader Status:" "bootupd-alternative" # Detect bootloader type local bootloader bootloader=$(detect_bootloader) echo " Type: $bootloader" case "$bootloader" in "uefi") get_uefi_status ;; "grub") get_grub_status ;; "lilo") get_lilo_status ;; "syslinux") get_syslinux_status ;; *) echo " Status: Unknown bootloader type" ;; esac } # Get UEFI status get_uefi_status() { echo " UEFI Status:" # Check EFI partition if mountpoint -q /boot/efi 2>/dev/null; then echo " EFI Partition: Mounted at /boot/efi" else echo " EFI Partition: Not mounted" fi # Check efibootmgr if command -v efibootmgr &> /dev/null; then echo " efibootmgr: Available" # Get current boot order local boot_order boot_order=$(efibootmgr 2>/dev/null | grep "BootOrder" | cut -d' ' -f2) if [[ -n "$boot_order" ]]; then echo " Boot Order: $boot_order" fi else echo " efibootmgr: Not available" fi } # Get GRUB status get_grub_status() { echo " GRUB Status:" # Check GRUB configuration if [[ -f "/boot/grub/grub.cfg" ]]; then echo " Configuration: /boot/grub/grub.cfg exists" local config_size config_size=$(stat -c %s /boot/grub/grub.cfg 2>/dev/null) if [[ -n "$config_size" ]]; then echo " Config Size: ${config_size} bytes" fi else echo " Configuration: /boot/grub/grub.cfg not found" fi # Check GRUB tools if command -v grub-install &> /dev/null; then echo " grub-install: Available" else echo " grub-install: Not available" fi if command -v grub-mkconfig &> /dev/null; then echo " grub-mkconfig: Available" else echo " grub-mkconfig: Not available" fi # Check GRUB modules if [[ -d "/boot/grub/x86_64-efi" ]]; then echo " Modules: EFI modules available" elif [[ -d "/boot/grub/i386-pc" ]]; then echo " Modules: Legacy modules available" else echo " Modules: No modules found" fi } # Get LILO status get_lilo_status() { echo " LILO Status:" # Check LILO configuration if [[ -f "/etc/lilo.conf" ]]; then echo " Configuration: /etc/lilo.conf exists" local config_size config_size=$(stat -c %s /etc/lilo.conf 2>/dev/null) if [[ -n "$config_size" ]]; then echo " Config Size: ${config_size} bytes" fi else echo " Configuration: /etc/lilo.conf not found" fi # Check LILO tool if command -v lilo &> /dev/null; then echo " lilo: Available" else echo " lilo: Not available" fi } # Get syslinux status get_syslinux_status() { echo " syslinux Status:" # Check syslinux configuration if [[ -f "/boot/syslinux/syslinux.cfg" ]]; then echo " Configuration: /boot/syslinux/syslinux.cfg exists" local config_size config_size=$(stat -c %s /boot/syslinux/syslinux.cfg 2>/dev/null) if [[ -n "$config_size" ]]; then echo " Config Size: ${config_size} bytes" fi else echo " Configuration: /boot/syslinux/syslinux.cfg not found" fi # Check syslinux tool if command -v syslinux &> /dev/null; then echo " syslinux: Available" else echo " syslinux: Not available" fi } # Get device status get_device_status() { log_info "Device Status:" "bootupd-alternative" # Find boot device local boot_device boot_device=$(find_boot_device) if [[ -n "$boot_device" ]]; then echo " Boot Device: $boot_device" # Get device information get_device_info "$boot_device" else echo " Boot Device: Could not determine" fi # Check mount points echo " Mount Points:" if mountpoint -q /boot 2>/dev/null; then local boot_mount boot_mount=$(findmnt -n -o SOURCE,TARGET,FSTYPE /boot 2>/dev/null) echo " /boot: $boot_mount" else echo " /boot: Not mounted" fi if mountpoint -q /boot/efi 2>/dev/null; then local efi_mount efi_mount=$(findmnt -n -o SOURCE,TARGET,FSTYPE /boot/efi 2>/dev/null) echo " /boot/efi: $efi_mount" else echo " /boot/efi: Not mounted" fi # Disk usage calculate_disk_usage "/" } # Get backup status get_backup_status() { log_info "Backup Status:" "bootupd-alternative" if [[ ! -d "$BOOTUPD_DIR/backups" ]]; then echo " Backups: No backup directory found" return fi local backup_count=0 local total_size=0 for backup_dir in "$BOOTUPD_DIR/backups"/*; do if [[ -d "$backup_dir" ]]; then backup_count=$((backup_count + 1)) local backup_size backup_size=$(du -s "$backup_dir" 2>/dev/null | cut -f1) if [[ -n "$backup_size" ]]; then total_size=$((total_size + backup_size)) fi fi done echo " Backup Count: $backup_count" echo " Total Size: ${total_size} KB" if [[ $backup_count -gt 0 ]]; then echo " Recent Backups:" for backup_dir in "$BOOTUPD_DIR/backups"/*; do if [[ -d "$backup_dir" ]]; then local backup_name backup_name=$(basename "$backup_dir") local backup_date backup_date=$(stat -c %y "$backup_dir" 2>/dev/null | cut -d' ' -f1) echo " $backup_name (created: $backup_date)" fi done fi } # Get integration status get_integration_status() { log_info "Integration Status:" "bootupd-alternative" # Check Ubuntu uBlue configuration if [[ -f "/usr/local/etc/ublue-config.sh" ]]; then echo " Ubuntu uBlue Config: Available" elif [[ -f "/etc/ublue-config.sh" ]]; then echo " Ubuntu uBlue Config: Available (system-wide)" else echo " Ubuntu uBlue Config: Not found" fi # Check ComposeFS integration if [[ -f "/usr/local/bin/composefs-alternative.sh" ]]; then echo " ComposeFS Integration: Available" elif [[ -f "/usr/bin/composefs-alternative.sh" ]]; then echo " ComposeFS Integration: Available (system-wide)" else echo " ComposeFS Integration: Not found" fi # Check bootloader integration if [[ -f "/usr/local/bin/bootc-alternative.sh" ]]; then echo " Bootloader Integration: Available" elif [[ -f "/usr/bin/bootc-alternative.sh" ]]; then echo " Bootloader Integration: Available (system-wide)" else echo " Bootloader Integration: Not found" fi # Check apt-layer integration if [[ -f "/usr/local/bin/apt-layer.sh" ]]; then echo " APT Layer Integration: Available" elif [[ -f "/usr/bin/apt-layer.sh" ]]; then echo " APT Layer Integration: Available (system-wide)" else echo " APT Layer Integration: Not found" fi } # Check system health check_system_health() { log_info "System Health Check:" "bootupd-alternative" local health_score=100 local issues=() # Check bootloader local bootloader bootloader=$(detect_bootloader) if [[ "$bootloader" == "unknown" ]]; then health_score=$((health_score - 20)) issues+=("Unknown bootloader type") fi # Check EFI partition for UEFI systems if [[ "$bootloader" == "uefi" ]]; then if ! mountpoint -q /boot/efi 2>/dev/null; then health_score=$((health_score - 15)) issues+=("EFI partition not mounted") fi fi # Check GRUB configuration for GRUB systems if [[ "$bootloader" == "grub" ]]; then if [[ ! -f "/boot/grub/grub.cfg" ]]; then health_score=$((health_score - 15)) issues+=("GRUB configuration missing") fi fi # Check disk space local available_space available_space=$(get_available_space "/") if [[ $? -eq 0 ]]; then local min_space=104857600 # 100MB if [[ $available_space -lt $min_space ]]; then health_score=$((health_score - 10)) issues+=("Low disk space") fi else health_score=$((health_score - 5)) issues+=("Cannot check disk space") fi # Check backup directory if [[ ! -d "$BOOTUPD_DIR/backups" ]]; then health_score=$((health_score - 5)) issues+=("No backup directory") fi # Report health status if [[ $health_score -ge 90 ]]; then echo " Health Status: Excellent ($health_score/100)" elif [[ $health_score -ge 75 ]]; then echo " Health Status: Good ($health_score/100)" elif [[ $health_score -ge 60 ]]; then echo " Health Status: Fair ($health_score/100)" else echo " Health Status: Poor ($health_score/100)" fi if [[ ${#issues[@]} -gt 0 ]]; then echo " Issues Found:" for issue in "${issues[@]}"; do echo " - $issue" done else echo " Issues Found: None" fi } # Monitor bootloader changes monitor_bootloader_changes() { local watch_interval="${1:-60}" # Default 60 seconds log_info "Starting bootloader change monitoring (interval: ${watch_interval}s)" "bootupd-alternative" # Create temporary file for tracking changes local temp_file temp_file=$(mktemp) # Initial state get_bootloader_state > "$temp_file" while true; do sleep "$watch_interval" # Get current state local current_state current_state=$(get_bootloader_state) # Compare with previous state if ! diff "$temp_file" <(echo "$current_state") > /dev/null 2>&1; then log_warning "Bootloader configuration changes detected!" "bootupd-alternative" echo "Changes:" diff "$temp_file" <(echo "$current_state") || true # Update state file echo "$current_state" > "$temp_file" fi done } # Get bootloader state for monitoring get_bootloader_state() { local bootloader bootloader=$(detect_bootloader) case "$bootloader" in "grub") if [[ -f "/boot/grub/grub.cfg" ]]; then stat -c "%Y %s" /boot/grub/grub.cfg fi ;; "lilo") if [[ -f "/etc/lilo.conf" ]]; then stat -c "%Y %s" /etc/lilo.conf fi ;; "syslinux") if [[ -f "/boot/syslinux/syslinux.cfg" ]]; then stat -c "%Y %s" /boot/syslinux/syslinux.cfg fi ;; "uefi") if command -v efibootmgr &> /dev/null; then efibootmgr 2>/dev/null | grep "BootOrder" fi ;; esac } # --- END OF SCRIPTLET: 06-status.sh --- # ============================================================================ # Main Dispatch and Help # ============================================================================ # Main execution and command dispatch for Ubuntu uBlue bootupd-alternative Tool # Show usage information show_usage() { cat << EOF Ubuntu uBlue bootupd-alternative Tool - Enhanced Bootloader Management Provides advanced bootloader management for Ubuntu uBlue systems Usage: bootupd-alternative install # Install bootloader to specified device bootupd-alternative update # Update bootloader configuration bootupd-alternative status # Show current bootloader status bootupd-alternative backup [name] # Create backup of current bootloader configuration bootupd-alternative restore # Restore bootloader configuration from backup bootupd-alternative list-backups # List available backups bootupd-alternative add-entry <kernel> [options] # Add new boot entry bootupd-alternative remove-entry <title> # Remove boot entry bootupd-alternative list-entries # List current boot entries bootupd-alternative set-default <title> # Set default boot entry bootupd-alternative info <device> # Show device information bootupd-alternative help # Show this help message Examples: # Install bootloader to device sudo bootupd-alternative install /dev/sda # Update bootloader configuration sudo bootupd-alternative update # Create backup sudo bootupd-alternative backup before-update # Restore backup sudo bootupd-alternative restore before-update # Add custom boot entry sudo bootupd-alternative add-entry "Ubuntu Recovery" /boot/vmlinuz-5.15.0-rc1 # Set default boot entry sudo bootupd-alternative set-default "Ubuntu uBlue" # Show device information sudo bootupd-alternative info /dev/sda Description: bootupd-alternative provides comprehensive bootloader management for Ubuntu uBlue systems. It supports multiple bootloader types (GRUB, UEFI, LILO, syslinux) and provides advanced features like backup/restore, custom boot entries, and device management. KEY FEATURES: - Multi-bootloader support (GRUB, UEFI, LILO, syslinux) - Automatic bootloader detection and configuration - Backup and restore functionality - Custom boot entry management - Device validation and information - Integration with Ubuntu uBlue configuration system SECURITY FEATURES: - Input validation and sanitization - Path traversal protection - Privilege escalation prevention - Secure temporary file handling INTEGRATION: - Ubuntu uBlue configuration system - ComposeFS backend support - Bootloader integration scripts - Unified logging system EOF } # Main execution main() { # Initialize directories init_directories # Check dependencies check_dependencies # Check system bootability check_system_bootability # Check filesystems check_filesystems # Parse command line arguments case "${1:-}" in --help|-h) show_usage exit 0 ;; install) if [ -z "${2:-}" ]; then log_error "Device required for install" "bootupd-alternative" show_usage exit 1 fi install_bootloader "$2" ;; update) update_bootloader ;; status) show_status ;; backup) local backup_name="${2:-backup-$(date +%Y%m%d-%H%M%S)}" create_backup "$backup_name" ;; restore) if [ -z "${2:-}" ]; then log_error "Backup name required for restore" "bootupd-alternative" show_usage exit 1 fi restore_backup "$2" ;; list-backups) list_backups ;; add-entry) if [ $# -lt 3 ]; then log_error "Title and kernel required for add-entry" "bootupd-alternative" show_usage exit 1 fi local title="$2" local kernel="$3" shift 3 local options=("$@") add_boot_entry "$title" "$kernel" "${options[@]}" ;; remove-entry) if [ -z "${2:-}" ]; then log_error "Title required for remove-entry" "bootupd-alternative" show_usage exit 1 fi remove_boot_entry "$2" ;; list-entries) list_boot_entries ;; set-default) if [ -z "${2:-}" ]; then log_error "Title required for set-default" "bootupd-alternative" show_usage exit 1 fi set_default_entry "$2" ;; info) if [ -z "${2:-}" ]; then log_error "Device required for info" "bootupd-alternative" show_usage exit 1 fi get_device_info "$2" ;; "") log_error "No arguments provided" "bootupd-alternative" show_usage exit 1 ;; *) log_error "Unknown command: $1" "bootupd-alternative" show_usage exit 1 ;; esac } # Run main function if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi # --- END OF SCRIPTLET: 99-main.sh --- # ============================================================================ # Embedded Configuration Files # ============================================================================ # ============================================================================ # External Configuration Loading (Future Enhancement) # ============================================================================ # Function to load configuration from external files # Usage: load_config_from_file "config-name" load_config_from_file() { local config_name="$1" local config_file="/etc/bootupd/config/${config_name}.json" if [[ -f "$config_file" ]]; then jq -r '.' "$config_file" else log_error "Configuration file not found: $config_file" "bootupd-alternative" exit 1 fi }