#!/bin/sh
# Copyright (C) 2026 by ALT Linux Team,
# Egor Ignatov <egori@altlinux.org>.
#
# grub-efi-sh-functions - shared helpers for the grub EFI shell scripts.
# POSIX sh, sourced by absolute path; callers set PROG for diagnostics.

# --- Shared constants ---

# GPT partition type GUID of the EFI System Partition
ESP_PARTTYPE_GUID="c12a7328-f81f-11d2-ba4b-00a0c93ec93b"

GRUB_SYSCONF="/etc/sysconfig/grub2"

# bootloader_id when GRUB_BOOTLOADER_ID is unset in GRUB_SYSCONF
DEFAULT_BOOTLOADER_ID="altlinux"

# --- ESP path resolution ---
#
# FAT name lookup can be case-sensitive (iocharset=utf8, check=s), so
# match names in userspace and reuse the spelling already on disk.

# esp_resolve_name DIR NAME: print the on-disk spelling of NAME in DIR
esp_resolve_name() (
    set +f      # esp_resolve_path calls us with globbing disabled
    dir="$1" want="$2"
    lower_want="$(printf '%s' "$want" | tr '[:upper:]' '[:lower:]')"
    found=
    nmatches=0
    for entry in "$dir"/*; do
        [ -e "$entry" ] || [ -L "$entry" ] || continue
        name="${entry##*/}"
        if [ "$name" = "$want" ]; then
            printf '%s\n' "$name"
            return 0
        fi
        if [ "$(printf '%s' "$name" | tr '[:upper:]' '[:lower:]')" = "$lower_want" ]; then
            [ -n "$found" ] || found="$name"
            nmatches=$((nmatches + 1))
        fi
    done
    if [ -n "$found" ]; then
        if [ "$nmatches" -gt 1 ]; then
            echo "${PROG:-grub-efi}: warning: $nmatches case-insensitive matches for '$want' in $dir; using '$found'" >&2
        fi
        printf '%s\n' "$found"
        return 0
    fi
    printf '%s\n' "$want"
)

# esp_resolve_path BASE RELPATH: resolve every component of RELPATH under BASE
esp_resolve_path() (
    set -f
    out="$1"
    rel="$2"
    IFS=/
    for comp in $rel; do
        [ -n "$comp" ] || continue
        out="$out/$(esp_resolve_name "$out" "$comp")"
    done
    printf '%s\n' "$out"
)

# --- ESP auto-discovery ---

# esp_find: print the mounted ESP (/boot/efi, /efi, /boot); return 1 if none
esp_find() (
    for candidate in /boot/efi /efi /boot; do
        findmnt -n "$candidate" > /dev/null 2>&1 || continue
        if [ "$(grub-probe -t gpt_parttype "$candidate" 2>/dev/null)" \
                 = "$ESP_PARTTYPE_GUID" ]; then
            printf '%s\n' "$candidate"
            return 0
        fi
    done
    if findmnt -n /boot/efi > /dev/null 2>&1; then
        echo "${PROG:-grub-efi}: warning: /boot/efi does not look like an ESP (GPT partition type GUID mismatch); using as fallback" >&2
        printf '%s\n' /boot/efi
        return 0
    fi
    return 1
)

# --- Architecture mapping ---

# efi_arch_info MACHINE: print "efi_suffix efi_suffix_upper grub_target"; return 1 if unknown
efi_arch_info() (
    case "$1" in
        x86_64)      printf '%s %s %s\n' x64         X64         x86_64-efi ;;
        i?86)        printf '%s %s %s\n' ia32        IA32        i386-efi ;;
        aarch64)     printf '%s %s %s\n' aa64        AA64        arm64-efi ;;
        loongarch64) printf '%s %s %s\n' loongarch64 LOONGARCH64 loongarch64-efi ;;
        riscv64)     printf '%s %s %s\n' riscv64     RISCV64     riscv64-efi ;;
        *)           return 1 ;;
    esac
)
