#!/bin/bash
#
# Copyright (C) 2026 by ALT Linux Team,
# Egor Ignatov <egori@altlinux.org>.
#
# grub-efi-install - Install GRUB EFI binaries to ESP with Secure Boot support
#
# This script handles three installation modes:
# - SECURE_BOOT: signed shim + grub chain (shim, mm, fb, grub, BOOT.CSV)
# - SIGNED: pre-built grub EFI binary without shim
# - PLAIN: delegate to vanilla grub-install (for architectures without
#   pre-built binaries)
#

set -efuo pipefail

PROG="${0##*/}"

# Exit codes
EXIT_SUCCESS=0
EXIT_PREFLIGHT=1
EXIT_INSTALL=2
EXIT_NVRAM=3

ESP_PARTTYPE_GUID="c12a7328-f81f-11d2-ba4b-00a0c93ec93b"

# Defaults
efi_directory=""
opt_efi_directory_set=0
efi_bindir=""
opt_efi_bindir_set=0
bootloader_id=""
boot_directory="/boot"
opt_removable=0
opt_force_extra_removable=0
opt_no_nvram=0
opt_first_install=0
opt_target=""
opt_mode="auto"
opt_verbose=0
opt_dry_run=0
grub_install_extra_args=()

GRUB_SYSCONF="/etc/sysconfig/grub2"

# --- Logging ---

info() {
    echo "$PROG: $*" >&2
}

verbose() {
    [ "$opt_verbose" = 1 ] && echo "$PROG: $*" >&2 ||:
}

error() {
    echo "$PROG: error: $*" >&2
}

die() {
    local rc="$1"; shift
    error "$@"
    exit "$rc"
}

# --- Architecture detection ---

detect_arch() {
    local machine
    machine="${opt_target:-$(uname -m)}"

    case "$machine" in
        x86_64)
            efi_suffix="x64"
            efi_suffix_upper="X64"
            grub_target="x86_64-efi"
            ;;
        i?86)
            efi_suffix="ia32"
            efi_suffix_upper="IA32"
            grub_target="i386-efi"
            ;;
        aarch64)
            efi_suffix="aa64"
            efi_suffix_upper="AA64"
            grub_target="arm64-efi"
            ;;
        loongarch64)
            efi_suffix="loongarch64"
            efi_suffix_upper="LOONGARCH64"
            grub_target="loongarch64-efi"
            ;;
        riscv64)
            efi_suffix="riscv64"
            efi_suffix_upper="RISCV64"
            grub_target="riscv64-efi"
            ;;
        *)
            die $EXIT_PREFLIGHT "unsupported architecture: $machine"
            ;;
    esac

    verbose "architecture: $machine -> efi_suffix=$efi_suffix, grub_target=$grub_target"
}

# --- EFI binary directory ---

find_efi_bindir() {
    if [ "$opt_efi_bindir_set" = 1 ]; then
        if [ ! -d "$efi_bindir" ]; then
            die $EXIT_PREFLIGHT \
                "EFI binary directory does not exist: $efi_bindir"
        fi
        verbose "efi_bindir=$efi_bindir (user-specified)"
        return
    fi

    if [ -d /usr/lib64/efi ]; then
        efi_bindir="/usr/lib64/efi"
    elif [ -d /usr/lib/efi ]; then
        efi_bindir="/usr/lib/efi"
    else
        efi_bindir=""
        info "no EFI binary directory found, will use plain mode"
    fi

    verbose "efi_bindir=${efi_bindir:-<none>}"
}

# --- Mode detection ---

detect_mode() {
    local have_shim=0 have_grub=0

    if [ -n "$efi_bindir" ]; then
        [ -f "$efi_bindir/shim${efi_suffix}.efi" ] && have_shim=1
        [ -f "$efi_bindir/grub${efi_suffix}.efi" ] && have_grub=1
    fi

    case "$opt_mode" in
        auto)
            if [ "$have_shim" = 1 ] && [ "$have_grub" = 1 ]; then
                install_mode="SECURE_BOOT"
            elif [ "$have_grub" = 1 ]; then
                install_mode="SIGNED"
            else
                install_mode="PLAIN"
            fi
            ;;
        secure-boot)
            if [ "$have_shim" = 0 ] || [ "$have_grub" = 0 ]; then
                die $EXIT_PREFLIGHT \
                    "--mode=secure-boot requires shim${efi_suffix}.efi and grub${efi_suffix}.efi in ${efi_bindir:-/usr/lib64/efi}"
            fi
            install_mode="SECURE_BOOT"
            ;;
        signed)
            if [ "$have_grub" = 0 ]; then
                die $EXIT_PREFLIGHT \
                    "--mode=signed requires grub${efi_suffix}.efi in ${efi_bindir:-/usr/lib64/efi}"
            fi
            install_mode="SIGNED"
            ;;
        plain)
            install_mode="PLAIN"
            ;;
    esac

    # --force-extra-removable is incompatible with SECURE_BOOT
    if [ "$install_mode" = "SECURE_BOOT" ] && [ "$opt_force_extra_removable" = 1 ]; then
        info "--force-extra-removable ignored in SECURE_BOOT mode"
        opt_force_extra_removable=0
    fi

    # --efi-binary-dir is not used in PLAIN mode
    if [ "$install_mode" = "PLAIN" ] && [ "$opt_efi_bindir_set" = 1 ]; then
        info "--efi-binary-dir ignored in plain mode"
    fi

    verbose "install_mode=$install_mode (shim=$have_shim, grub=$have_grub)"
}

# --- Validation ---

validate_esp() {
    if [ -z "$efi_directory" ]; then
        die $EXIT_PREFLIGHT "ESP directory not specified and auto-discovery failed"
    fi

    if ! findmnt -n "$efi_directory" > /dev/null 2>&1; then
        die $EXIT_PREFLIGHT "ESP is not mounted at $efi_directory"
    fi

    if [ ! -d "$efi_directory" ]; then
        die $EXIT_PREFLIGHT "ESP directory does not exist: $efi_directory"
    fi

    if [ ! -w "$efi_directory" ]; then
        die $EXIT_PREFLIGHT "ESP directory is not writable: $efi_directory"
    fi

    verbose "ESP validated: $efi_directory"
}

validate_nvram_access() {
    if [ "$opt_no_nvram" = 1 ] || [ "$opt_removable" = 1 ]; then
        return 0
    fi

    # Ensure efivarfs is mounted for efibootmgr to access EFI variables
    if ! mountpoint -q /sys/firmware/efi/efivars 2>/dev/null; then
        mount -t efivarfs efivarfs /sys/firmware/efi/efivars 2>/dev/null ||
            die $EXIT_PREFLIGHT \
                "EFI variables not available (failed to mount efivarfs at /sys/firmware/efi/efivars)"
    fi

    if ! command -v efibootmgr > /dev/null 2>&1; then
        die $EXIT_PREFLIGHT "efibootmgr not found; install it or use --no-nvram"
    fi

    verbose "NVRAM access validated"
}

# --- ESP auto-discovery ---

find_esp() {
    local candidate parttype

    for candidate in /boot/efi /efi /boot; do
        findmnt -n "$candidate" > /dev/null 2>&1 || continue
        parttype="$(grub-probe -t gpt_parttype "$candidate" 2>/dev/null)" || continue

        if [ "$parttype" = "$ESP_PARTTYPE_GUID" ]; then
            efi_directory="$candidate"
            verbose "auto-detected ESP: $candidate"
            return 0
        fi
    done

    # Fallback: use /boot/efi without GUID check if it is mounted
    if findmnt -n /boot/efi > /dev/null 2>&1; then
        info "warning: /boot/efi does not look like an ESP (GPT partition type GUID mismatch); using as fallback"
        efi_directory="/boot/efi"
        return 0
    fi

    die $EXIT_PREFLIGHT "no ESP found at /boot/efi, /efi, or /boot"
}

# --- grub.cfg / BOOT.CSV generation ---

generate_grub_cfg() {
    local dest_dir="$1"
    local cfg_path="${dest_dir}/grub.cfg"
    local grub_relpath crypto_content="" search_cmd hints

    grub_relpath="$(grub-mkrelpath "$boot_directory/grub")" \
        || die $EXIT_PREFLIGHT "failed to determine relative path via grub-mkrelpath"

    # Search hints for faster device discovery (non-critical)
    hints="$(grub-probe --target=hints_string "$boot_directory/grub" 2>/dev/null)" || hints=""

    # Cryptodisk support
    if [ "${GRUB_ENABLE_CRYPTODISK-}" = "y" ]; then
        local crypto_uuids
        crypto_uuids="$(grub-probe --target=cryptodisk_uuid "$boot_directory/grub")" \
            || die $EXIT_PREFLIGHT "failed to determine cryptodisk UUIDs via grub-probe"
        local uuid
        if [ -n "$crypto_uuids" ]; then
            while IFS= read -r uuid; do
                crypto_content="${crypto_content}cryptomount -A -u ${uuid}
"
            done <<< "$crypto_uuids"
        fi
    fi

    # Root device identification: prefer fs_uuid, fall back to file marker
    local root_uuid
    root_uuid="$(grub-probe --target=fs_uuid "$boot_directory/grub" 2>/dev/null)" || root_uuid=""

    if [ -n "$root_uuid" ]; then
        search_cmd="search --root-dev-only --set=root --fs-uuid ${root_uuid}${hints:+ $hints}"
    else
        # File-based identification fallback (same approach as grub-install)
        local rndfile
        rndfile="$(mktemp -u XXXXXXXXXXXXXXXXXXXXXXXX)"
        mkdir -p "$boot_directory/grub/uuid"
        : > "$boot_directory/grub/uuid/$rndfile"
        local relpath
        relpath="$(grub-mkrelpath "$boot_directory/grub/uuid/$rndfile")"
        search_cmd="search.file ${relpath} root${hints:+ $hints}"
    fi

    local content="${crypto_content}${search_cmd}
set prefix=(\$root)${grub_relpath}
configfile \$prefix/grub.cfg
"

    if [ "$opt_dry_run" = 1 ]; then
        info "would write $cfg_path:"
        printf '%s' "$content" >&2
        return
    fi

    mkdir -p "$dest_dir"
    printf '%s' "$content" > "${cfg_path}.new"
    mv "${cfg_path}.new" "$cfg_path"
    verbose "wrote $cfg_path"
}

generate_boot_csv() {
    local dest_dir="$1"
    local csv_path="${dest_dir}/BOOT${efi_suffix_upper}.CSV"
    local content="shim${efi_suffix}.efi,${nvram_label},,This is the boot entry for ${bootloader_id}"

    if [ "$opt_dry_run" = 1 ]; then
        info "would write $csv_path:"
        printf '%s\n' "$content" >&2
        return
    fi

    mkdir -p "$dest_dir"
    printf '%s\n' "$content" | iconv -t UCS-2LE > "${csv_path}.new"
    mv "${csv_path}.new" "$csv_path"
    verbose "wrote $csv_path"
}

# --- Safe file copy ---

safe_copy() {
    local src="$1" dst="$2"

    if [ "$opt_dry_run" = 1 ]; then
        info "would copy $src -> $dst"
        return 0
    fi

    if [ ! -f "$src" ]; then
        error "source file not found: $src"
        return 1
    fi

    cp -f "$src" "${dst}.new"
    mv "${dst}.new" "$dst"
    verbose "copied $src -> $dst"
}

# --- grub-install ---

run_grub_install() {
    local args=()

    case "$install_mode" in
        SECURE_BOOT|SIGNED)
            args=(--target="$grub_target"
                  --boot-directory="$boot_directory"
                  --boot-directory-only)
            ;;
        PLAIN)
            args=(--target="$grub_target"
                  --boot-directory="$boot_directory"
                  --no-nvram)
            [ "$opt_removable" = 1 ] && args+=(--removable)
            args+=(--efi-directory="$efi_directory"
                   --bootloader-id="$bootloader_id")
            ;;
    esac

    if [ "${#grub_install_extra_args[@]}" -gt 0 ]; then
        verbose "extra grub-install args: ${grub_install_extra_args[*]}"
    fi

    if [ "$opt_dry_run" = 1 ]; then
        info "would run: grub-install ${args[*]} ${grub_install_extra_args[*]}"
        return
    fi

    info "running grub-install ${args[*]} ${grub_install_extra_args[*]}"

    grub-install "${args[@]}" "${grub_install_extra_args[@]}" \
        || die $EXIT_INSTALL "grub-install failed"
}

# --- Installation functions ---

install_secure_boot() {
    local vendor_dir="$efi_directory/EFI/$bootloader_id"
    local boot_dir="$efi_directory/EFI/BOOT"

    info "installing Secure Boot binaries to ESP"

    local shim_src="$efi_bindir/shim${efi_suffix}.efi"
    local grub_src="$efi_bindir/grub${efi_suffix}.efi"
    local mm_src="$efi_bindir/mm${efi_suffix}.efi"
    local fb_src="$efi_bindir/fb${efi_suffix}.efi"

    if [ "$opt_removable" = 1 ]; then
        mkdir -p "$boot_dir"
        safe_copy "$shim_src" "$boot_dir/BOOT${efi_suffix_upper}.EFI"
        safe_copy "$mm_src"   "$boot_dir/mm${efi_suffix}.efi"
        safe_copy "$grub_src" "$boot_dir/grub${efi_suffix}.efi"
        generate_grub_cfg "$boot_dir"
    else
        mkdir -p "$vendor_dir" "$boot_dir"
        safe_copy "$shim_src" "$vendor_dir/shim${efi_suffix}.efi"
        safe_copy "$mm_src"   "$vendor_dir/mm${efi_suffix}.efi"
        safe_copy "$grub_src" "$vendor_dir/grub${efi_suffix}.efi"
        generate_grub_cfg "$vendor_dir"
        generate_boot_csv "$vendor_dir"
        safe_copy "$shim_src" "$boot_dir/BOOT${efi_suffix_upper}.EFI"
        safe_copy "$mm_src"   "$boot_dir/mm${efi_suffix}.efi"
        safe_copy "$fb_src"   "$boot_dir/fb${efi_suffix}.efi"
    fi
}

install_signed() {
    local vendor_dir="$efi_directory/EFI/$bootloader_id"
    local boot_dir="$efi_directory/EFI/BOOT"

    info "installing pre-built GRUB binary to ESP"

    local grub_src="$efi_bindir/grub${efi_suffix}.efi"

    if [ "$opt_removable" = 1 ]; then
        mkdir -p "$boot_dir"
        safe_copy "$grub_src" "$boot_dir/BOOT${efi_suffix_upper}.EFI"
        generate_grub_cfg "$boot_dir"
    else
        mkdir -p "$vendor_dir"
        safe_copy "$grub_src" "$vendor_dir/grub${efi_suffix}.efi"
        generate_grub_cfg "$vendor_dir"
        if [ "$opt_force_extra_removable" = 1 ]; then
            mkdir -p "$boot_dir"
            safe_copy "$grub_src" "$boot_dir/BOOT${efi_suffix_upper}.EFI"
            generate_grub_cfg "$boot_dir"
        fi
    fi
}

install_plain_extra_removable() {
    local vendor_dir="$efi_directory/EFI/$bootloader_id"
    local boot_dir="$efi_directory/EFI/BOOT"

    info "copying PLAIN fallback binary to $boot_dir"

    mkdir -p "$boot_dir"
    safe_copy "$vendor_dir/grub${efi_suffix}.efi" \
        "$boot_dir/BOOT${efi_suffix_upper}.EFI"
}

# --- Stale file cleanup ---

cleanup_stale_files() {
    local dir="$1"; shift

    for file in "$@"; do
        local path="$dir/$file"
        [ -f "$path" ] || continue

        if [ "$opt_dry_run" = 1 ]; then
            info "would remove stale $path"
        else
            rm -f "$path"
            verbose "removed stale $path"
        fi
    done
}

cleanup_esp() {
    local vendor_dir="$efi_directory/EFI/$bootloader_id"
    local boot_dir="$efi_directory/EFI/BOOT"

    case "$install_mode" in
        SECURE_BOOT)
            if [ "$opt_removable" = 1 ]; then
                cleanup_stale_files "$boot_dir" \
                    "fb${efi_suffix}.efi" \
                    "shim${efi_suffix}.efi" \
                    "BOOT${efi_suffix_upper}.CSV"
            else
                cleanup_stale_files "$boot_dir" \
                    "grub${efi_suffix}.efi" \
                    "grub.cfg" \
                    "shim${efi_suffix}.efi" \
                    "BOOT${efi_suffix_upper}.CSV"
                cleanup_stale_files "$vendor_dir" \
                    "fb${efi_suffix}.efi"
            fi
            ;;
        SIGNED)
            if [ "$opt_removable" = 1 ]; then
                cleanup_stale_files "$boot_dir" \
                    "grub${efi_suffix}.efi" \
                    "shim${efi_suffix}.efi" \
                    "mm${efi_suffix}.efi" \
                    "fb${efi_suffix}.efi" \
                    "BOOT${efi_suffix_upper}.CSV"
            else
                cleanup_stale_files "$vendor_dir" \
                    "shim${efi_suffix}.efi" \
                    "mm${efi_suffix}.efi" \
                    "fb${efi_suffix}.efi" \
                    "BOOT${efi_suffix_upper}.CSV"
                if [ "$opt_force_extra_removable" = 1 ]; then
                    cleanup_stale_files "$boot_dir" \
                        "grub${efi_suffix}.efi" \
                        "shim${efi_suffix}.efi" \
                        "mm${efi_suffix}.efi" \
                        "fb${efi_suffix}.efi" \
                        "BOOT${efi_suffix_upper}.CSV"
                fi
            fi
            ;;
        PLAIN)
            if [ "$opt_removable" = 1 ]; then
                cleanup_stale_files "$boot_dir" \
                    "mm${efi_suffix}.efi" \
                    "fb${efi_suffix}.efi" \
                    "grub${efi_suffix}.efi" \
                    "grub.cfg" \
                    "BOOT${efi_suffix_upper}.CSV"
            else
                cleanup_stale_files "$vendor_dir" \
                    "shim${efi_suffix}.efi" \
                    "mm${efi_suffix}.efi" \
                    "fb${efi_suffix}.efi" \
                    "grub.cfg" \
                    "BOOT${efi_suffix_upper}.CSV"
                if [ "$opt_force_extra_removable" = 1 ]; then
                    cleanup_stale_files "$boot_dir" \
                        "shim${efi_suffix}.efi" \
                        "mm${efi_suffix}.efi" \
                        "fb${efi_suffix}.efi" \
                        "grub${efi_suffix}.efi" \
                        "grub.cfg" \
                        "BOOT${efi_suffix_upper}.CSV"
                fi
            fi
            ;;
    esac
}

# --- NVRAM management ---

get_esp_disk_and_part() {
    local esp_source

    esp_source="$(grub-probe -t device "$efi_directory" | head -n1)" \
        || die $EXIT_NVRAM "failed to determine ESP source device for $efi_directory"

    esp_disk="$(grub-probe -t disk "$efi_directory" | head -n1)" \
        || die $EXIT_NVRAM "failed to determine ESP disk for $efi_directory"

    # Extract partition number by stripping the disk prefix from the device path
    # e.g. /dev/sda1 - /dev/sda = 1; /dev/nvme0n1p2 - /dev/nvme0n1 = p2 -> 2
    esp_partnum="${esp_source#"$esp_disk"}"
    esp_partnum="${esp_partnum#p}"

    case "$esp_partnum" in
        *[!0-9]*|"") die $EXIT_NVRAM "cannot determine partition number for $esp_source (disk=$esp_disk)" ;;
    esac

    verbose "ESP device: disk=$esp_disk partnum=$esp_partnum (source=$esp_source)"
}

find_nvram_entry() {
    local efi_output

    efi_output="$(efibootmgr 2>/dev/null)" || return 0

    nvram_boot_order="$(echo "$efi_output" | sed -n 's/^BootOrder: //p')"

    # Match by label using exact string comparison.
    # efibootmgr output format: "Boot<4hex><'*'/' '> <label>\t<device_path>"
    # cut -f1: extract first tab-delimited field (strip device path).
    # ${entry:10}: strip 10-char prefix "Boot0000* " to get the label.
    # [[ == ]] with quoted RHS: exact string match, no glob/regex.
    local entry label
    nvram_bootnum=""
    for label in "$nvram_label" "$bootloader_id"; do
        while IFS= read -r entry; do
            if [[ "${entry:10}" == "$label" ]]; then
                nvram_bootnum="${entry:4:4}"; break 2
            fi
        done < <(echo "$efi_output" | cut -f1 | grep '^Boot[0-9A-Fa-f]\{4\}[* ]')
    done

    verbose "NVRAM: bootnum=${nvram_bootnum:-<none>} boot_order=${nvram_boot_order:-<none>}"
}

manage_nvram() {
    if [ "$opt_no_nvram" = 1 ] || [ "$opt_removable" = 1 ]; then
        verbose "NVRAM update skipped (no_nvram=$opt_no_nvram, removable=$opt_removable)"
        return 0
    fi

    get_esp_disk_and_part
    find_nvram_entry

    local efi_path
    if [ "$install_mode" = "SECURE_BOOT" ]; then
        efi_path="\\EFI\\${bootloader_id}\\shim${efi_suffix}.efi"
    else
        efi_path="\\EFI\\${bootloader_id}\\grub${efi_suffix}.efi"
    fi

    local do_first_install=0
    if [ "$opt_first_install" = 1 ] || [ -z "$nvram_bootnum" ]; then
        do_first_install=1
    fi

    if [ "$opt_dry_run" = 1 ]; then
        info "would update NVRAM: disk=$esp_disk part=$esp_partnum path=$efi_path (first_install=$do_first_install)"
        return 0
    fi

    # Delete old entry if it exists
    if [ -n "$nvram_bootnum" ]; then
        efibootmgr -q -b "$nvram_bootnum" -B || :
    fi

    # Create new entry
    if [ "$do_first_install" = 0 ] && [ -n "$nvram_bootnum" ]; then
        # Update: reuse old boot number
        efibootmgr -q -c -d "$esp_disk" -p "$esp_partnum" \
            -L "$nvram_label" -l "$efi_path" -b "$nvram_bootnum" \
            || die $EXIT_NVRAM "failed to create NVRAM boot entry"
    else
        efibootmgr -q -c -d "$esp_disk" -p "$esp_partnum" \
            -L "$nvram_label" -l "$efi_path" \
            || die $EXIT_NVRAM "failed to create NVRAM boot entry"
    fi

    if [ "$do_first_install" = 0 ]; then
        # Restore original boot order so we don't shuffle priorities
        if [ -n "$nvram_boot_order" ]; then
            efibootmgr -q -o "$nvram_boot_order" || :
            verbose "restored BootOrder: $nvram_boot_order"
        fi
    else
        local new_boot_order
        new_boot_order="$(efibootmgr | sed -n 's/^BootOrder: //p')"
        info "new BootOrder: ${new_boot_order:-<unknown>}"
    fi

    info "NVRAM entry registered: '$nvram_label' $efi_path"
}

# --- Argument parsing ---

usage() {
    cat >&2 <<EOF
Usage: $PROG [OPTIONS]

Install GRUB EFI binaries to the EFI System Partition.
Supports Secure Boot when signed shim and grub binaries are available.

Mode selection:
  --mode MODE              Installation mode (default: auto)
                           auto        - detect from available EFI binaries
                           secure-boot - shim + grub chain (requires shim and grub)
                           signed      - pre-built grub binary (requires grub)
                           plain       - delegate to vanilla grub-install

Installation modes:
  --removable              Install to EFI/BOOT/ only (removable media)
  --force-extra-removable  Vendor path + EFI/BOOT/ (no Secure Boot only)

NVRAM control:
  --no-nvram               Do not modify NVRAM
  --first-install          Force first position in BootOrder

Paths:
  --boot-directory DIR     Boot directory (default: /boot)
  --efi-directory DIR      ESP root (default: auto-detect)
  --efi-binary-dir DIR     Pre-built EFI binaries (default: /usr/lib64/efi)
  --bootloader-id ID       Directory name under EFI/ (default: from sysconfig)

Architecture:
  --target ARCH            Override architecture (default: uname -m)
                           Values: x86_64, i586, aarch64, loongarch64, riscv64

Other:
  --verbose                Verbose output
  --dry-run                Show what would be done without executing
  --help                   Show this help

  -- [ARGS...]             Pass remaining arguments directly to grub-install
EOF
}

parse_args() {
    local temp
    temp="$(getopt -o '' \
        --long removable,force-extra-removable,no-nvram,first-install \
        --long boot-directory:,efi-directory:,efi-binary-dir:,bootloader-id:,target:,mode: \
        --long verbose,dry-run,help \
        -n "$PROG" -- "$@")" \
        || die $EXIT_PREFLIGHT "invalid arguments (use --help)"

    eval set -- "$temp"

    while true; do
        case "$1" in
            --removable)             opt_removable=1; shift ;;
            --force-extra-removable) opt_force_extra_removable=1; shift ;;
            --no-nvram)              opt_no_nvram=1; shift ;;
            --first-install)         opt_first_install=1; shift ;;
            --boot-directory)        boot_directory="$2"; shift 2 ;;
            --efi-directory)         efi_directory="$2"; opt_efi_directory_set=1; shift 2 ;;
            --efi-binary-dir)        efi_bindir="$2"; opt_efi_bindir_set=1; shift 2 ;;
            --bootloader-id)         bootloader_id="$2"; shift 2 ;;
            --target)                opt_target="$2"; shift 2 ;;
            --mode)                  opt_mode="$2"; shift 2 ;;
            --verbose)               opt_verbose=1; shift ;;
            --dry-run)               opt_dry_run=1; opt_verbose=1; shift ;;
            --help)                  usage; exit 0 ;;
            --)                      shift; break ;;
            *)                       break ;;
        esac
    done

    grub_install_extra_args=("$@")

    if [ "$opt_removable" = 1 ] && [ "$opt_force_extra_removable" = 1 ]; then
        die $EXIT_PREFLIGHT "--removable and --force-extra-removable are mutually exclusive"
    fi

    case "$opt_mode" in
        auto|secure-boot|signed|plain) ;;
        *) die $EXIT_PREFLIGHT "unknown --mode value: $opt_mode (use auto, secure-boot, signed, plain)" ;;
    esac
}

# --- Config loading ---

load_config() {
    if [ -f "$GRUB_SYSCONF" ]; then
        . "$GRUB_SYSCONF"
    fi

    # Command-line --bootloader-id takes priority over sysconfig
    if [ -z "$bootloader_id" ]; then
        bootloader_id="${GRUB_BOOTLOADER_ID:-altlinux}"
    fi

    # GRUB_DISTRIBUTOR is the human-readable label for NVRAM boot entries
    nvram_label="${GRUB_DISTRIBUTOR:-$bootloader_id}"
}

# --- Main ---

main() {
    parse_args "$@"
    load_config

    # Auto-discover ESP only when --efi-directory was not specified
    if [ "$opt_efi_directory_set" = 0 ]; then
        find_esp
    fi

    detect_arch
    find_efi_bindir
    detect_mode
    validate_esp
    validate_nvram_access

    info "mode=$install_mode, bootloader_id=$bootloader_id, efi_directory=$efi_directory"

    run_grub_install

    case "$install_mode" in
        SECURE_BOOT) install_secure_boot ;;
        SIGNED) install_signed ;;
        PLAIN)
            if [ "$opt_force_extra_removable" = 1 ]; then
                install_plain_extra_removable
            fi
            ;;
    esac

    cleanup_esp

    manage_nvram

    info "installation finished successfully"
    exit $EXIT_SUCCESS
}

main "$@"
