#!/usr/bin/env bash
#
#   Script name: ubboot
#   Description: Script for managing boot
#   GitLab: https://gitea.ublinux.ru/
#   Author: Dmitry Razumov <asmeron@ublinux.com>
#   Contributors: UBGroup support <support@ublinux.com>
#
#   Copyright (c) 2021-2025 UBLinux Development Team <support@ublinux.ru>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

VERSION_SCRIPT=2.17

# Exit Immediately if a command fails
#set -o errexit

#################################
###   :::   C O L O R S   :::   #
#################################
set_color() {
#http://abload.de/img/bash-color-chartmxjbp.png
    export BBC=$'\e[1;34m'
    export RBC=$'\e[1;31m'
    export WBC=$'\e[1m'
    export EC=$'\e[0m'

    export txtblk='\033[0;30m' # Black - Regular
    export txtred='\033[0;31m' # Red			# prompt: error color
    export txtgrn='\033[0;32m' # Green			# prompt: success color
    export txtylw='\033[0;33m' # Yellow			# prompt: waring color
    export txtblu='\033[0;34m' # Blue			
    export txtpur='\033[0;35m' # Purple
    export txtcyn='\033[0;36m' # Cyan			# prompt: info color
    export txtwht='\033[0;37m' # White
    export bldblk='\033[1;30m' # Black - Bold
    export bldred='\033[1;31m' # Red			# prompt: bold error color
    export bldgrn='\033[1;32m' # Green			# prompt: bold success color
    export bldylw="\033[1;33m" # Yellow                 # prompt: bold warning color
    export bldblu='\033[1;34m' # Blue				
    export bldpur='\033[1;35m' # Purple
    export bldcyn="\033[1;36m" # Cyan                   # prompt: bold info color
    export bldwht="\033[1;37m" # White			# prompt: bold default color

    export undblk='\033[4;30m' # Black - Underline
    export undred='\033[4;31m' # Red

    export bakblk='\033[40m'   # Black - Background
    export bakred='\033[41m'   # Red
    export badgrn='\033[42m'   # Green

    export txtrst='\033[0m'    # Text Reset		# prompt: default color
}

#######################################
###   :::   F U N C T I O N S   :::   #
#######################################

check_root() {
    if [[ ${EUID:-$(id -u)} > 0 ]]; then
        prompt -wq "Please run as root!"
    fi
}

# Check command availability
has_command() { command -v $1 &> /dev/null; }

 # echo like ... with flag type and display message colors
prompt() {
    [[ -n ${QUIET} ]] && return
    case ${1} in
	-s  | --success)	echo -e "${bldgrn}${@/#-s/}${txtrst}" ;;    			# print success message
	-sq | --success-quit)	echo -e "${bldgrn}${@/#-sq/}${txtrst}" && exit 1 ;;    		# print success message
	-e  | --error)   	echo -e "${bldred}ERROR:${@/#-e/}${txtrst}" ;;   		# print error message
	-eq | --error-quit)   	echo -e "${bldred}ERROR:${@/#-eq/}${txtrst}" && exit 1 ;;	# print error message
	-w  | --warning) 	echo -e "${bldylw}WARNING:${bldwht}${@/#-w/}${txtrst}" ;; 	# print warning message
	-wq | --warning-quit) 	echo -e "${bldylw}WARNING:${bldwht}${@/#-wq/}${txtrst}" && exit 1 ;; # print warning message
	-i  | --info)    	echo -e "${bldcyn}INFO:${txtcyn}${@/#-i/}${txtrst}" ;;    	# print info message
	-iq | --info-quit)    	echo -e "${bldcyn}INFO:${txtcyn}${@/#-iq/}${txtrst}" && exit 1 ;;  # print info message
	*)    			echo -e "$@" ;;							# print all message
    esac
}

usage() {
    printf "%s  %s\n" "${0##*/}" "version: ${VERSION_SCRIPT}"
    cat <<EOF
Manage boot OS

Usage: ${0##*/} {COMMAND} [OPTIONS]

Commands:
  create		  Create a new root skeleton
  update		  Update GRUB, boot.tar.xz, ublinux-data.tar.xz on boot partitional
Meta Commands:
  help          	  Show this help

OPTIONS:
  -p, --path-media=<PATH> Path to the root /ublinux/
			  Without option for command 'create' PATH="./"
			  Without option for command 'update' PATH="/mnt/livemedia"
      --path-data=<PATH>  Path to the root /ublinux-data/
			  Without option for command 'create' PATH="./"
			  Without option for command 'update' PATH="/mnt/livedata"
      --path-boot=<PATH>  Path to the root /boot/
			  Without option for command 'create' PATH="./"
			  Without option for command 'update' PATH="/mnt/livemedia"
  -u, --skel-ublinux	  Create/Update skeleton '/ublinux'
    			  The system settings will return to default "ublinux.ini"
  -d, --skel-data	  Create/Update skeleton '/ublinux-data'
    			  The system settings will return to default "ublinux.ini"
  -g, --skel-grub	  Create/Update skeleton GRUB binary and configure '/boot/'
			  If command 'create', then create binary and configure '/boot/'
			  If command 'update', then update only configure '/boot/grub/ublinux/'
  -t, --grub-theme=<THEME> Create/Update GRUB theme '/boot/'
    <THEME>=<NAME_THEME>  Grub theme name
    <THEME>=auto          Automatically choose theme
  -s, --sign=<SIGN>	  New signature name .sgn
    <SIGN>=<NUMBER>	  Number 6 digits
    <SIGN>=auto	  	  Automatically generate sign number
			  If the set --sign and <SIGN> empty, then --sign=auto
      --pkg-newver	  New version of the package for applying the update patch
      --pkg-oldver	  Old version of the package for applying the update patch
  -q, --quiet		  Quiet mode
  -h, --help		  Show this help
  -V, --version		  Show package version

OPTIONS for 'update' command only:
  -t, --grub-theme=<NAME> Create/Update GRUB theme
            		  If the grub theme [NAME] is not found,
            		  then automatically select from the found installed theme
Examples:
${0##*/} create -udgs
${0##*/} update -ugs iso -p /home/iso
${0##*/} update -d -p /mnt/livemedia
EOF
    exit 0
}

arguments() {
# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
    local ARGV=()
    local END_OF_OPT=
    while [[ $# -gt 0 ]]; do
	arg="$1"; shift
	case "${END_OF_OPT}${arg}" in
	    --) ARGV+=("$arg"); END_OF_OPT=1 ;;
	    --*=*)ARGV+=("${arg%%=*}" "${arg#*=}") ;;
	    --*) ARGV+=("$arg") ;;
	    -*) for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
	    *) ARGV+=("$arg") ;;
	esac
    done
# Apply pre-processed options
    set -- "${ARGV[@]}"
# Parse options
    local END_OF_OPT=
    local POSITIONAL_ARGS=()
    [[ -z $@ ]] && usage && exit 0
    while [[ $# -gt 0 ]]; do
	case "${END_OF_OPT}${1}" in
	    -h | --help | help)	  usage ;;
	    -p | --path-media)	  shift; PATH_ROOT_MEDIA="$1" ;;
	         --path-data)	  shift; PATH_ROOT_DATA="$1" ;;
	         --path-boot)	  shift; PATH_ROOT_BOOT="$1" ;;
	    -u | --skel-ublinux)  SKEL_UBLINUX=1 ;;
	    -d | --skel-data)	  SKEL_DATA=1 ;;
	    -g | --skel-grub)	  SKEL_GRUB=1 ;;
	    -s | --sign)	  [[ -n $2 ]] && ! grep -q "^-" <<< "$2" && shift && GEN_SGN="$1" || GEN_SGN="auto";;
	    -t | --grub-theme)	  [[ -n $2 ]] && ! grep -q "^-" <<< "$2" && shift && GRUB_THEME_NAME="$1" || GRUB_THEME_NAME="auto";;
		 --pkg-newver)	  shift; PKG_NEWVER="$1" ;;
		 --pkg-oldver)	  shift; PKG_OLDVER="$1" ;;
	    -q | --quiet)     	  QUIET=1 ;;
	    -V | --version)	  echo "Version: ${VERSION_SCRIPT}"; exit 0 ;;
	    update)    		  COMMAND="update" ;;
	    create)    		  COMMAND="create" ;;
	    --stdin)        	  READ_STDIN=1 ;;
	    --)             	  END_OF_OPT=1 ;;
	    -*|--*)         	  echo "WARNING: Unrecognized argument, skiped: $1" >&2  ;;
	    *)              	  POSITIONAL_ARGS+=("$1") ;;
	esac
	shift
    done
# Restore positional parameters
    set -- "${POSITIONAL_ARGS[@]}"
    [[ -z ${COMMAND} ]] && usage
    [[ ${GEN_SGN,,} == "auto" ]] && GEN_SGN=$(shuf -i 1-1000000 -n 1)
    if [[ ${COMMAND} == "create" ]]; then
	[[ -z ${PATH_ROOT_MEDIA} ]] && PATH_ROOT_MEDIA="${PATH_WORK}" && PATH_ROOT_DATA="${PATH_WORK}" && PATH_ROOT_BOOT="${PATH_WORK}"
    elif [[ ${COMMAND} == "update" ]]; then
	[[ -z ${PATH_ROOT_MEDIA} ]] && PATH_ROOT_MEDIA="/mnt/livemedia" && PATH_ROOT_DATA="/mnt/livedata" && PATH_ROOT_BOOT="/mnt/livemedia"
    fi
    [[ -z ${PATH_ROOT_DATA} ]] && PATH_ROOT_DATA="${PATH_ROOT_MEDIA}"
    [[ -z ${PATH_ROOT_BOOT} ]] && PATH_ROOT_BOOT="${PATH_ROOT_MEDIA}"

    [[ -n ${PATH_ROOT_MEDIA} ]] && PATH_ROOT_MEDIA=$(realpath ${PATH_ROOT_MEDIA})
    [[ -n ${PATH_ROOT_DATA} ]] && PATH_ROOT_DATA=$(realpath ${PATH_ROOT_DATA})
    [[ -n ${PATH_ROOT_BOOT} ]] && PATH_ROOT_BOOT=$(realpath ${PATH_ROOT_BOOT})

    [[ -w ${PATH_ROOT_MEDIA} ]] || prompt -eq "path not write ${PATH_ROOT_MEDIA}"
    [[ -w ${PATH_ROOT_DATA} ]] || prompt -eq "path not write ${PATH_ROOT_DATA}"
    [[ -w ${PATH_ROOT_BOOT} ]] || prompt -eq "path not write ${PATH_ROOT_BOOT}"
}

check_lib() {
    [[ -d ${PATH_UBBOOT_LIB} ]] || prompt -eq "path not found ${PATH_UBBOOT_LIB}"
    [[ -d ${PATH_TEMPLATE} ]] || prompt -eq "path not found ${PATH_TEMPLATE}"
    [[ -d ${PATH_TEMPLATE_UBINIT} ]] || prompt -eq "path not found ${PATH_TEMPLATE_UBINIT}"
    [[ -f ${FILE_LICENSE} ]] || prompt -eq "file not found ${FILE_LICENSE}"
    [[ -d ${PATH_GRUB_SHARE} ]] || prompt -eq "path not found ${PATH_GRUB_SHARE}"
    [[ -d ${PATH_GRUB_LIB} ]] || prompt -eq "path not found ${PATH_GRUB_LIB}"
    [[ -d ${PATH_LOCALE} ]] || prompt -eq "path not found ${PATH_LOCALE}"
}

install_pkg() {
    if [[ ${COMMAND} == "create" || -n ${SKEL_GRUB} ]]; then
	true
#	if ! pacman -Qqs memtest86+ > /dev/null; then
#	    prompt -i "install 'memtest86+' package"
#	    sudo pacman --noconfirm -Sqy memtest86+
#	fi
    fi
}

oper_grub() {
    patch_2_17(){
    # Fix version < 2.17
	prompt -i "apply patch for version ${PKG_OLDVER} <= 2.17"
        # Удалить старые не используемые файлы с меткой локализации
        find "${PATH_ROOT_GRUB}"/ublinux/ -maxdepth 1 -regextype sed -regex ".*/grub_\(en\|ru\)\(\|_addon\|_boothdd\|_recovery\|_settings\|_settings_kernel\|_settings_saveclean\)\.cfg.\?" -delete
	# Обновляем каталог locale/*.mo т.к. содеражатся новые переводы
	cd "${PATH_LOCALE}"
	find . -type f -name "grub.mo" -exec /bin/bash -c '[[ ${1} =~ .*/([^/]+)/LC_MESSAGES/grub.mo ]] && install -CDm0644 "${1}" "${2}"/locale/${BASH_REMATCH[1]}.mo' _ {} "${PATH_ROOT_GRUB}" \;
        # Модифицируем grubenv, переходим на --id
        local GRUBENV_SAVE_ENTRY= GRUBENV_NEW_ENTRY=
	local FILE_GRUBENV="${PATH_ROOT_GRUB}/grubenv"
	if [[ -w ${FILE_GRUBENV} ]]; then
    	    [[ $(< ${FILE_GRUBENV}) =~ (^|$'\n')"saved_entry="([^$'\n']+)$'\n' ]] && GRUBENV_SAVE_ENTRY=${BASH_REMATCH[2]}
    	    [[ ${GRUBENV_SAVE_ENTRY} =~ .*" - Полное сохранение HDD" ]] && GRUBENV_NEW_ENTRY="Full_save_to_HDD"
            [[ ${GRUBENV_SAVE_ENTRY} =~ .*" - Песочница в RAM с сохранением профиля пользователя HDD" ]] && GRUBENV_NEW_ENTRY="Sandbox_in_RAM_with_save_user_profile_on_HDD"
            [[ ${GRUBENV_SAVE_ENTRY} =~ .*" - Полная песочница в RAM" ]] && GRUBENV_NEW_ENTRY="Full_sandbox_in_RAM"
            [[ ${GRUBENV_SAVE_ENTRY} =~ .*" - Сохранение в модуль HDD" ]] && GRUBENV_NEW_ENTRY="Saving_to_the_HDD_module"
            #Menu_of_the_second_system 
            [[ ${GRUBENV_SAVE_ENTRY} =~ "Меню дополнительное>".*" - Песочница на HDD с сохранением профиля пользователя HDD" ]] && GRUBENV_NEW_ENTRY="Additional_Menu>Sandbox_on_HDD_with_saving_user_profile_on_HDD"
            [[ ${GRUBENV_SAVE_ENTRY} =~ "Меню дополнительное>".*" - Полная песочница на HDD" ]] && GRUBENV_NEW_ENTRY="Additional_Menu>Full_sandbox_on_HDD"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка Windows используя bootmgr (7, 8, 8.1, 10, 11, 12)" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_Windows_bootmgr"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка Windows используя ntldr (XP)" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_Windows_ntldr"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка Windows BIOS MBR" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_Windows_BIOS_MBR"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка Windows EFI boot раздел MBR" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_Windows_EFI_MBR"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №1, Windows EFI boot раздел MBR" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_1_Windows_EFI_MBR"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №2, Windows EFI boot раздел MBR" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_2_Windows_EFI_MBR"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №3, Windows EFI boot раздел MBR" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_3_Windows_EFI_MBR"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №4, Windows EFI boot раздел MBR" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_4_Windows_EFI_MBR"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка Windows EFI boot раздел GPT" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_Windows_EFI_GPT"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №1, Windows EFI boot раздел GPT" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_1_Windows_EFI_GPT"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №2, Windows EFI boot раздел GPT" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_2_Windows_EFI_GPT"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №3, Windows EFI boot раздел GPT" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_3_Windows_EFI_GPT"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №4, Windows EFI boot раздел GPT" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_4_Windows_EFI_GPT"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №2, маскируем диск под первый загрузочный" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_2_masking"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №3, маскируем диск под первый загрузочный" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_3_masking"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №4, маскируем диск под первый загрузочный" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_4_masking"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №2, без маскировки" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_2_without_masking"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №3, без маскировки" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_3_without_masking"
            [[ ${GRUBENV_SAVE_ENTRY} == "Меню выбора загрузки других ОС>Загрузка с диска №4, без маскировки" ]] && GRUBENV_NEW_ENTRY="Boot_menu_for_other_OS>Boot_from_storage_4_without_masking"
            if [[ -n ${GRUBENV_NEW_ENTRY} ]]; then
	        local DATA_GRUBENV=$(cat <<EOF
# GRUB Environment Block
saved_entry=${GRUBENV_NEW_ENTRY}
EOF
)
	        LC_ALL=C
#	        echo -e "${DATA_GRUBENV}$(yes "" | head -n $((1024-"${#DATA_GRUBENV}")) | tr \\n '#')" > "${PATH_GRUB}/grubenv"
	        echo -ne "${DATA_GRUBENV}\n$(printf -- '#'%.s $(seq -s ' ' $((1023-"${#DATA_GRUBENV}"))))" > "${FILE_GRUBENV}"
	    fi
	fi
    }
    local PATH_ROOT_BOOT="$1/boot"
    local PATH_ROOT_GRUB="${PATH_ROOT_BOOT}/grub"
    local LOCAL_COMMAND="$2"
    [[ ! -d ${PATH_ROOT_GRUB} && ${LOCAL_COMMAND} == "update" ]] || install -dm0755 -o root -g root ${PATH_ROOT_GRUB}/ublinux
    if [[ -d ${PATH_ROOT_GRUB} ]]; then
        prompt -i "update GRUB configure to ${PATH_ROOT_GRUB}"
        # Если предыдущая версия ниже 2.17 то применить патч
        [[ ${LOCAL_COMMAND} == "update" && -n ${PKG_OLDVER} ]] && printf "${PKG_OLDVER}\n2.17" | sort --version-sort --check 2>/dev/null && patch_2_17
        install -CDm0640 "${PATH_GRUB_SHARE}/unicode.pf2" "${PATH_ROOT_GRUB}/fonts/unicode.pf2"
        install -CDm0640 "${PATH_GRUB_SHARE}/ascii.pf2" "${PATH_ROOT_GRUB}/fonts/ascii.pf2"
        install -CDm0640 "${PATH_GRUB_SHARE}/euro.pf2" "${PATH_ROOT_GRUB}/fonts/euro.pf2"
        cd "${PATH_TEMPLATE}/grub"
        install -CDbm0640 root_grub.cfg "${PATH_ROOT_GRUB}/grub.cfg"
        if [[ ${LOCAL_COMMAND} == "create" ]]; then
            install -CDbm0640 grubenv -t "${PATH_ROOT_GRUB}"
            install -CDbm0640 grub_var_user.cfg -t "${PATH_ROOT_GRUB}/ublinux"
        fi
        install -CDbm0640 -t "${PATH_ROOT_GRUB}/ublinux" \
            gfxmenu.cfg \
            grub.cfg \
            grub_addon.cfg \
            grub_boothdd.cfg \
            grub_lang.cfg \
            grub_local.cfg \
            grub_main.cfg \
            grub_recovery.cfg \
            grub_settings.cfg \
            grub_var.cfg \
            grub_var_locale.cfg \
            grub_var_user.cfg \
            modules.cfg
        install -CDbm0644 -t "${PATH_ROOT_GRUB}/locale/gmo" ./gmo/*
        install -dm0750 -o root -g root "${PATH_ROOT_GRUB}/ublinux/themes"
        prompt -i "install Memtest86+"
        [[ -d /boot/memtest86+ ]] && cp -a /boot/memtest86+ "${PATH_ROOT_BOOT}/"
        [[ -d /boot/memtest86 ]] && cp -a /boot/memtest86 "${PATH_ROOT_BOOT}/"
	FILE_EFI_SHELL_X64="${PATH_TEMPLATE_EFISHELL}/x64/Shell_Full.efi"
	if [[ -f ${FILE_EFI_SHELL_X64} ]]; then
	    prompt -i "install ED2K EFI Shell x64"
	    [[ -d ${PATH_ROOT_BOOT}/grub/ublinux/efi ]] || install -dm0750 -o root -g root "${PATH_ROOT_BOOT}/grub/ublinux/efi"
	    install -CDbm0640 "${FILE_EFI_SHELL_X64}" "${PATH_ROOT_BOOT}/grub/ublinux/efi/shellx64.efi"
	else
	    prompt -w "not installed package 'ed2k-shell', not found ED2K EFI Shell x64 ${FILE_EFI_SHELL_X64}"
	fi
	FILE_EFI_SHELL_IA32="${PATH_TEMPLATE_EFISHELL}/ia32/Shell_Full.efi"
	if [[ -f ${FILE_EFI_SHELL_IA32} ]]; then
	    prompt -i "install ED2K EFI Shell IA32"
	    [[ -d ${PATH_ROOT_BOOT}/grub/ublinux/efi ]] || install -dm0750 -o root -g root "${PATH_ROOT_BOOT}/grub/ublinux/efi"
	    install -CDbm0640 "${FILE_EFI_SHELL_IA32}" "${PATH_ROOT_BOOT}/grub/ublinux/efi/shellia32.efi"
	else
	    prompt -w "not installed package 'ed2k-shell', not found ED2K EFI Shell IA32 ${FILE_EFI_SHELL_IA32}"
	fi
    else
        prompt -e "not found GRUB path ${PATH_ROOT_GRUB}"
	return 1
    fi
}

oper_grub_bin() {
    local PATH_ROOT_BOOT="$1/boot"
    local PATH_ROOT_GRUB="${PATH_ROOT_BOOT}/grub"
    local LOCAL_COMMAND="$2"
    [[ ! -d ${PATH_ROOT_GRUB} && ${LOCAL_COMMAND} == "update" ]] || install -dm0755 -o root -g root ${PATH_ROOT_GRUB}/ublinux
    if [[ -d ${PATH_ROOT_GRUB} ]]; then
        prompt -i "update GRUB binaries to ${PATH_ROOT_GRUB}"
	cd "${PATH_GRUB_LIB}"
	find . -type f -exec install -CDm0644 {} ${PATH_ROOT_GRUB}/{} \;
	cd "${PATH_LOCALE}"
	find . -type f -name "grub.mo" -exec /bin/bash -c '[[ ${1} =~ .*/([^/]+)/LC_MESSAGES/grub.mo ]] && install -CDm0644 "${1}" "${2}"/locale/${BASH_REMATCH[1]}.mo' _ {} "${PATH_ROOT_GRUB}" \;
    else
        prompt -e "not found GRUB path ${PATH_ROOT_GRUB}"
	return 1
    fi
}

oper_grub_theme() {
    local PATH_ROOT_UBLINUX="$1/ublinux"
    local PATH_ROOT_GRUB_THEMES="$2/boot/grub/ublinux/themes"
    local PATH_ROOT_GRUB_FONTS="$2/boot/grub/fonts"
    local PATH_THEME="${PATH_GRUB_SHARE}/themes"
    local GRUB_THEME_NAME="$3"
    local LOCAL_COMMAND="$4"
    [[ ! -d ${PATH_ROOT_GRUB_THEMES} && ${LOCAL_COMMAND} == "update" ]] || install -dm0755 -o root -g root ${PATH_ROOT_GRUB_THEMES}
    if [[ -z ${GRUB_THEME_NAME} || ${GRUB_THEME_NAME,,} == "auto" ]]; then
	if ls "${PATH_ROOT_UBLINUX}"/VERSION_* &> /dev/null; then
	    OS_RELEASE_PRETTY_NAME="$(cat ${PATH_ROOT_UBLINUX}/VERSION_* | head -1)"
	elif [[ -f /usr/lib/os-release ]]; then
	    OS_RELEASE_PRETTY_NAME="$(cat /usr/lib/os-release | grep "PRETTY_NAME=" | cut -d= -f2 | sed 's/"//g')"
	else
	    OS_RELEASE_PRETTY_NAME="UBLinux 0000 Unknown (x)"
	fi
	GRUB_THEME_NAME="$(${PATH_UBBOOT_LIB}/ubdistconv -d ${OS_RELEASE_PRETTY_NAME})"
    fi
    # If theme not found then select first found ublinux_*
    if [[ ! -d ${PATH_THEME}/${GRUB_THEME_NAME} && -d ${PATH_THEME} ]]; then
	prompt -w "GRUB theme '${GRUB_THEME_NAME}' not found!"
	GRUB_THEME_NAME="$(find ${PATH_THEME}/* -maxdepth 0 -type d -iname "*ublinux*" -print 2>/dev/null | head -1 | sed 's/.*\///')"
	[[ -n ${GRUB_THEME_NAME} ]] || GRUB_THEME_NAME="$(find ${PATH_THEME}/* -maxdepth 0 -type d -iname "*" -print 2>/dev/null | head -1 | sed 's/.*\///')"
	[[ -n ${GRUB_THEME_NAME} ]] && prompt -i "first found GRUB theme selected: ${GRUB_THEME_NAME}"
    fi
    if [[ -d ${PATH_ROOT_GRUB_THEMES} && -d ${PATH_THEME} ]]; then
        prompt -i "update GRUB theme '${GRUB_THEME_NAME}'"
        cd ${PATH_THEME}
        find ${GRUB_THEME_NAME}/ -type f ! -iname "*.pf2" -exec install -CDm0640 {} ${PATH_ROOT_GRUB_THEMES}/{} \;
	cd ${GRUB_THEME_NAME}
        find . -type f -iname "*.pf2" -exec install -CDm0640 {} ${PATH_ROOT_GRUB_FONTS}/{} \;
        chmod 0750 ${PATH_ROOT_GRUB_THEMES}/${GRUB_THEME_NAME}
    else
        prompt -e "not found GRUB theme path '${PATH_ROOT_GRUB_THEMES}'"
	return 1
    fi
}

oper_skel_ublinux() {
    local PATH_ROOT_UBLINUX="$1/ublinux"
    local LOCAL_COMMAND="$2"
    [[ ! -d ${PATH_ROOT_UBLINUX} && ${LOCAL_COMMAND} == "update" ]] || install -dm0755 -o root -g root ${PATH_ROOT_UBLINUX}
    if [[ -d ${PATH_ROOT_UBLINUX} ]]; then
        prompt -i "update skeleton '${PATH_ROOT_UBLINUX}'"
	install -dm0750 -o root -g root \
	    "${PATH_ROOT_UBLINUX}/base" \
	    "${PATH_ROOT_UBLINUX}/machines/dynamic" \
	    "${PATH_ROOT_UBLINUX}/machines/static" \
	    "${PATH_ROOT_UBLINUX}/modules" \
	    "${PATH_ROOT_UBLINUX}/install/preinit" \
	    "${PATH_ROOT_UBLINUX}/optional"
	install -CDm0644 "${FILE_LICENSE}" "${PATH_ROOT_UBLINUX}/LICENSE"
	if [[ ${LOCAL_COMMAND} == "create" ]]; then
	    install -CDm0640 "${PATH_TEMPLATE_UBINIT}/ublinux.ini" "${PATH_ROOT_UBLINUX}/ublinux.ini"
	fi
	ls "${PATH_ROOT_UBLINUX}"/ublinux-*.sgn &>/dev/null || install -CDm0640 "${PATH_TEMPLATE_UBINIT}/ublinux.sgn" "${PATH_ROOT_UBLINUX}/ublinux.sgn"
	build_boot_tarxz "${PATH_ROOT_UBLINUX}"
	build_skel_ublinux_data_tarxz "${PATH_ROOT_UBLINUX}"
    else
        prompt -e "not found skeleton path '${PATH_ROOT_UBLINUX}'"
	return 1
    fi
}

oper_skel_ublinux_data() {
    local PATH_ROOT_UBLINUX_DATA="$1/ublinux-data"
    local LOCAL_COMMAND="$2"
    [[ ! -d ${PATH_ROOT_UBLINUX_DATA} && ${LOCAL_COMMAND} == "update" ]] || install -dm0755 -o root -g root ${PATH_ROOT_UBLINUX_DATA}
    if [[ -d ${PATH_ROOT_UBLINUX_DATA} ]]; then
        prompt -i "update skeleton '${PATH_ROOT_UBLINUX_DATA}'"
	install -dm0750 -o root -g root \
	    "${PATH_ROOT_UBLINUX_DATA}/cache" \
	    "${PATH_ROOT_UBLINUX_DATA}/modules" \
	    "${PATH_ROOT_UBLINUX_DATA}/optional" \
	    "${PATH_ROOT_UBLINUX_DATA}/upgrade"
	install -dm0755 -o root -g root \
	    "${PATH_ROOT_UBLINUX_DATA}/homes" \
	    "${PATH_ROOT_UBLINUX_DATA}/changes" \
	    "${PATH_ROOT_UBLINUX_DATA}/machines/dynamic" \
	    "${PATH_ROOT_UBLINUX_DATA}/machines/static" \
	    "${PATH_ROOT_UBLINUX_DATA}/install/preinit" \
	    "${PATH_ROOT_UBLINUX_DATA}/rootcopy"
	if [[ ${LOCAL_COMMAND} == "create" ]]; then
	    install -CDm0640 "${PATH_TEMPLATE_UBINIT}/ublinux-data.ini" "${PATH_ROOT_UBLINUX_DATA}/ublinux.ini"
	elif [[ ${LOCAL_COMMAND} == "update" ]]; then
#	    cp --backup=numbered "${PATH_TEMPLATE_UBINIT}/ublinux-data.ini" "${PATH_ROOT_UBLINUX_DATA}/ublinux.ini"
#	    Запустить запись текущих настроек в обновлённый файл ublinux.ini
#	    ubconfig upgrade
	    chmod 0640 "${PATH_ROOT_UBLINUX_DATA}/ublinux.ini"
	fi
	ls "${PATH_ROOT_UBLINUX_DATA}"/ublinux-data*.sgn &>/dev/null || install -CDm0640 "${PATH_TEMPLATE_UBINIT}/ublinux-data.sgn" "${PATH_ROOT_UBLINUX_DATA}/ublinux-data.sgn"
    else
        prompt -e "not found skeleton path '${PATH_ROOT_UBLINUX_DATA}'"
	return 1
    fi
}

build_boot_tarxz() {
    local PATH_SAVE_TARXZ="$1"
    local PATH_TMP_TARXZ=$(mktemp -d /tmp/${PKGNAME}.XXXX)
    oper_grub "${PATH_TMP_TARXZ}" "create"
    oper_grub_bin "${PATH_TMP_TARXZ}" "create"
    oper_grub_theme "${PATH_TMP_TARXZ}" "${PATH_TMP_TARXZ}" "${GRUB_THEME_NAME}" "create"
    cd "${PATH_TMP_TARXZ}"
    tar -cvJf "${PATH_SAVE_TARXZ}/boot.tar.xz" "boot" >/dev/null 2>&1
    rm -rdf "${PATH_TMP_TARXZ}"
}

build_skel_ublinux_data_tarxz() {
    local PATH_SAVE_TARXZ="$1"
    local PATH_TMP_TARXZ=$(mktemp -d /tmp/${PKGNAME}.XXXX)
    oper_skel_ublinux_data "${PATH_TMP_TARXZ}" "create"
    cd "${PATH_TMP_TARXZ}"
    tar -cvJf "${PATH_SAVE_TARXZ}/ublinux-data.tar.xz" "ublinux-data" >/dev/null 2>&1
    rm -rdf "${PATH_TMP_TARXZ}"
}

update_grub_var_user() {
    local PATH_ROOT_MEDIA=$1
    local PATH_ROOT_DATA=$2
    local PATH_ROOT_BOOT=$3
    [[ -z ${PATH_ROOT_MEDIA} ]] || SGNFILE=$(ls ${PATH_ROOT_MEDIA}/ublinux/ublinux*.sgn 2>/dev/null | head -1)
    [[ -z ${PATH_ROOT_DATA} ]] || SGNFILE_DATA=$(ls ${PATH_ROOT_DATA}/ublinux-data/ublinux*.sgn 2>/dev/null | head -1)
    [[ -d ${PATH_ROOT_BOOT}/boot/grub/ublinux ]] && GRUB_VAR_USER="${PATH_ROOT_BOOT}/boot/grub/ublinux/grub_var_user.cfg" || return 1
    if [[ -n ${SGNFILE} ]]; then
	if [[ -n ${GEN_SGN} ]]; then
	    NEW_SGNFILE="${PATH_ROOT_MEDIA}/ublinux/ublinux-${GEN_SGN}.sgn"
	    mv -f "${SGNFILE}" "${NEW_SGNFILE}" &>/dev/null
	    SGNFILE="${NEW_SGNFILE}"
	fi
	if grep -q "^set SGNFILE=" "${GRUB_VAR_USER}" 2>/dev/null; then
	    sed -i "s/^\(set SGNFILE\s*=\s*\).*\$/\1${SGNFILE##*/}/" "${GRUB_VAR_USER}"
	else
	    echo "set SGNFILE=${SGNFILE##*/}" >> "${GRUB_VAR_USER}"
	    echo "export SGNFILE" >> "${GRUB_VAR_USER}"
	fi
	prompt -i "update sign GRUB ${SGNFILE} configure to ${GRUB_VAR_USER}"
    fi
    if [[ -n ${SGNFILE_DATA} ]]; then
	if [[ -n ${GEN_SGN} ]]; then
	    NEW_SGNFILE_DATA="${PATH_ROOT_DATA}/ublinux-data/ublinux-data-${GEN_SGN}.sgn"
	    mv -f "${SGNFILE_DATA}" "${NEW_SGNFILE_DATA}" &>/dev/null
	    SGNFILE_DATA="${NEW_SGNFILE_DATA}"
	fi
	if grep -q "^set SGNFILE_DATA=" "${GRUB_VAR_USER}" 2>/dev/null; then
	    sed -i "s/^\(set SGNFILE_DATA\s*=\s*\).*\$/\1${SGNFILE_DATA##*/}/" "${GRUB_VAR_USER}"
	else
	    echo "set SGNFILE_DATA=${SGNFILE_DATA##*/}" >> "${GRUB_VAR_USER}"
	    echo "export SGNFILE_DATA" >> "${GRUB_VAR_USER}"
	fi
	prompt -i "update sign GRUB ${SGNFILE_DATA} configure to ${GRUB_VAR_USER}"
    fi
    if [[ -n ${LANG} ]]; then
	echo "set LANG=${LANG%%_*}" >> "${GRUB_VAR_USER}"
	echo "export LANG" >> "${GRUB_VAR_USER}"
    fi
}

create() {
    if [[ -n ${SKEL_DATA} ]]; then
	oper_skel_ublinux_data "${PATH_ROOT_DATA}" "${COMMAND}" || { prompt -w "not create SKEL: ${PATH_ROOT_DATA}/ublinux-data/" && RESULT=1; }
    fi
    if [[ -n ${SKEL_UBLINUX} ]]; then
	oper_skel_ublinux "${PATH_ROOT_MEDIA}" "${COMMAND}" || { prompt -w "not create SKEL: ${PATH_ROOT_MEDIA}/ublinux/" && RESULT=1; }
    fi
    if [[ -n ${SKEL_GRUB} ]]; then
	oper_grub "${PATH_ROOT_BOOT}" "${COMMAND}" || { prompt -w "not create GRUB configuration: ${PATH_ROOT_BOOT}" && RESULT=1; }
	oper_grub_bin "${PATH_ROOT_BOOT}" "${COMMAND}" || { prompt -w "not copy GRUB binary: ${PATH_ROOT_BOOT}" && RESULT=1; }
	oper_grub_theme "${PATH_ROOT_MEDIA}" "${PATH_ROOT_BOOT}" "${GRUB_THEME_NAME}" "${COMMAND}" || { prompt -w "not create GRUB theme: ${GRUB_THEME_NAME}" && RESULT=1; }
	update_grub_var_user "${PATH_ROOT_MEDIA}" "${PATH_ROOT_DATA}" "${PATH_ROOT_BOOT}" "${COMMAND}" || { prompt -w "not update GRUB: grub_var_user.cfg" && RESULT=1; }
    fi
    [[ ${RESULT} < 1 ]] || return 1
}

update() {
    [[ -n ${SKEL_DATA} ]] && { oper_skel_ublinux_data "${PATH_ROOT_DATA}" "${COMMAND}" || { prompt -w "not update SKEL: ${PATH_ROOT_DATA}/ublinux-data/" && RESULT=1; }; }
    [[ -n ${SKEL_UBLINUX} ]] && { oper_skel_ublinux "${PATH_ROOT_MEDIA}" "${COMMAND}" || { prompt -w "not update SKEL: ${PATH_ROOT_MEDIA}/ublinux/" && RESULT=1; }; }
    [[ -n ${SKEL_GRUB} ]] && { oper_grub "${PATH_ROOT_BOOT}" "${COMMAND}" || { prompt -w "not update GRUB configuration: ${PATH_ROOT_BOOT}" && RESULT=1; }; }
    [[ -n ${SKEL_GRUB} || -n ${GEN_SGN} ]] && { update_grub_var_user "${PATH_ROOT_MEDIA}" "${PATH_ROOT_DATA}" "${PATH_ROOT_BOOT}" "${COMMAND}" || { prompt -w "not update GRUB: grub_var_user.cfg" && RESULT=1; }; }
    [[ -n ${GRUB_THEME_NAME} ]] && { oper_grub_theme "${PATH_ROOT_MEDIA}" "${PATH_ROOT_BOOT}" "${GRUB_THEME_NAME}" "${COMMAND}" || { prompt -w "not update GRUB theme: ${GRUB_THEME_NAME}" && RESULT=1; }; }
    [[ ${RESULT} < 1 ]] || return 1
}

###############################
###   :::   M A I N   :::   ###
###############################

    PKGNAME=${0##*/}
    PATH_WORK=$(realpath ${PWD})
    PATH_UBBOOT_LIB="/usr/lib/ubboot"
    PATH_TEMPLATE="/usr/share/ubboot"
    PATH_TEMPLATE_UBINIT="/usr/lib/ublinux/templates"
    PATH_TEMPLATE_EFISHELL="/usr/share/edk2-shell/"
    FILE_LICENSE="/usr/share/licenses/ublinux/LICENSE"
    PATH_GRUB_SHARE="/usr/share/grub"
    PATH_GRUB_LIB="/usr/lib/grub"
    PATH_LOCALE="/usr/share/locale"
    set_color
    arguments $@
    check_root
    check_lib
    install_pkg

    if [[ ${COMMAND} == "create" ]]; then
        create || prompt -eq "command CREATE not finished!"
    elif [[ ${COMMAND} == "update" ]]; then
        update || prompt -eq "command UPDATE not finished!"
    fi
