#!/bin/bash
# Libreria provisional para uso de UEFI
# Las funciones se incluirán las librerías ya existentes

#/**
#         ogNvramActiveEntry
#@brief   Activa entrada de la NVRAM identificada por la etiqueta o el orden
#@param    Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar.
#@return  (nada)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#*/ ##
function ogNvramActiveEntry () {
local NUMENTRY

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \
           "$FUNCNAME 2" \
	   "$FUNCNAME \"Windows Boot Manager\""
    return
fi

# Error si no se recibe 1 parámetro.
[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $?

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

# Distingo si es número de orden o etiqueta
if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then
    NUMENTRY=$( efibootmgr |awk  -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}')
else
    NUMENTRY=$(efibootmgr |awk  -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}')
fi

[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'")

efibootmgr -a -b $NUMENTRY &>/dev/null
}

#/**
#         ogNvramAddEntry
#@brief   Crea nueva entrada en el gestor de arranque (NVRAM), opcionalmente la incluye al final del orden de arranque.
#@param    Str_Label_entry Número de disco o etiqueta de la entrada a crear.
#@param    Str_BootLoader  Número de partición o cargador de arranque.
#@param    Bool_Incluir_Arranque  Incluir en el orden de arranque (por defecto FALSE) (opcional)
#@return  (nada)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#*/ ##
function ogNvramAddEntry () {
local EFIDISK EFIPART BOOTLABEL BOOTLOADER ADDORDER

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME Str_label_entry Str_boot_loader [ Bool_add_bootorder ]" \
           "$FUNCNAME 1 2 TRUE" \
           "$FUNCNAME grub /EFI/grub/grubx64.efi TRUE" \
           "$FUNCNAME Windows /EFI/Microsoft/Boot/bootmgfw.efi"
    return
fi

# Error si no se recibe 1 parámetro.
[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Str_label_entry Str_boot_locader" || return $?

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

read -e EFIDISK EFIPART <<<"$(ogGetEsp)"
[ -n "$EFIPART" ] || ogRaiseError $OG_ERR_NOTFOUND "ESP" || return $?

# Recogemos parámetros
# Distinguimos si es disco/partición o etiqueta/cargador
if [[ "$1$2" =~ ^([0-9]+)$ ]]; then
    BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2)
    BOOTLOADER="/EFI/$BOOTLABEL/Boot/ogloader.efi"
else
    BOOTLABEL="$1"
    BOOTLOADER="$2"
fi


# Si existe entrada con la misma etiqueta la borramos
ogNvramDeleteEntry "$BOOTLABEL" 2>/dev/null

efibootmgr -C -d $(ogDiskToDev $EFIDISK) -p $EFIPART -L "$BOOTLABEL" -l "$BOOTLOADER" &>/dev/null

# Incluimos la entrada en el orden de arranque (opcional)
if [ "${3^^}" == "TRUE" ]; then
    NUMENTRY=$(efibootmgr |awk  -v LABEL="$BOOTLABEL" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}')
    ogNvramSetOrder $(ogNvramGetOrder |tr , " ") $NUMENTRY
fi
}


#/**
#         ogCopyEfiBootLoader int_ndisk str_repo path_image
#@brief   Copia el cargador de arranque desde la partición EFI a la de sistema.
#@param   int_ndisk    nº de orden del disco
#@param   int_part     nº de partición
#@return  (nada, por determinar)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#@note    Si existe el cargador en la partición de sistema no es válido
#*/ ##
function ogCopyEfiBootLoader () {
# Variables locales
local MNTDIR EFIDIR BOOTLABEL OSVERSION LOADER f

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \
           "$FUNCNAME 1 2"
    return
fi

# Error si no se reciben 2 arámetros.
[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $?

# Comprobamos que exista partición de sistema y la  ESP
MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_PARTITION "$DISK $PART" || return $?
EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $?

# Comprobamos que exista el cargador
BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2)
OSVERSION=$(ogGetOsVersion $1 $2)
case $OSVERSION in
    *Windows\ 10*)
        for f in $EFIDIR/EFI/{Microsoft,$BOOTLABEL}/Boot/bootmgfw.efi; do
            [ -r $f ] && LOADER=$f
        done
        [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($OSVERSION, EFI)" || return $?
        # Si existe el directorio Boot lo borramos
        [ -d $MNTDIR/ogBoot ] && rm -rf $MNTDIR/ogBoot
        DIRLOADER=$(realpath "${LOADER%/*}/..")
        cp -r ${DIRLOADER}/Boot $MNTDIR/ogBoot
        ;;
esac
}


#/**
#         ogNvramDeleteEntry
#@brief   Borra entrada de la NVRAM identificada por la etiqueta o el orden
#@param    Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar.
#@return  (nada)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado (entrada en NVRAM).
#*/ ##
function ogNvramDeleteEntry () {
local NUMENTRY n

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \
           "$FUNCNAME 2" \
	   "$FUNCNAME \"Windows Boot Manager\""
    return
fi

# Error si no se recibe 1 parámetro.
[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $?

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

# Distingo si es número de orden o etiqueta
if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then
    NUMENTRY=$( efibootmgr |awk  -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}')
else
    NUMENTRY=$(efibootmgr |awk  -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}')
fi

[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'")

for n in $NUMENTRY; do
    efibootmgr -B -b $n &>/dev/null
done
}


#/**
#         ogNvramGetCurrent
#@brief   Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo.
#@return  Entrada con la que se ha iniciado el equipo
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#*/ ##
function ogNvramGetCurrent () {

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME" \
           "$FUNCNAME"
    return
fi

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

efibootmgr| awk -v bootentry=99999 '{if ($1~/BootCurrent/) bootentry=$2; if ($1~bootentry) printf  "%s %s %s\n", gensub(/^0{1,3}/,"",1,substr($1,5,4))," ", substr($0, index($0,$2))}'
}


#         ogNvramGetNext
#@brief   Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque.
#@return  Entrada que se utilizará en el próximo arranque
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#*/ ##
function ogNvramGetNext () {
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME" \
           "$FUNCNAME"
    return
fi

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

efibootmgr|awk '{ if ($1 == "BootNext:") print $2}'
}


#         ogNvramGetOrder
#@brief   Muestra el orden de las entradas del gestor de arranque (NVRAM)
#@return  Orden de las entradas
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#*/ ##
function ogNvramGetOrder () {
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME" \
           "$FUNCNAME"
    return
fi

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

efibootmgr|awk '{ if ($1 == "BootOrder:") print $2}'
}


#/**
#         ogNvramGetTimeout
#@brief   Muestra el tiempo de espera del gestor de arranque (NVRAM)
#@return  Timeout de la NVRAM
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#*/ ##
function ogNvramGetTimeout () {
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME" \
           "$FUNCNAME"
    return
fi

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

efibootmgr|awk '{ if ($1 == "Timeout:") print substr($0, index($0,$2))}'
}


#/**
#         ogGrubUefiConf int_ndisk int_part str_dir_grub
#@brief   Genera el fichero grub.cfg de la ESP
#@param   int_ndisk    nº de orden del disco
#@param   int_part     nº de partición
#@param   str_dir_grub prefijo del directorio de grub en la partición de sistema. ej: /boot/grubPARTITION
#@return  (nada, por determinar)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#@TODO    Confirmar si el fichero "$EFIDIR/EFI/$BOOTLABEL/grub.cfg" es necesario.
#*/ ##
function ogGrubUefiConf () {
local EFIDIR BOOTLABEL GRUBEFI UUID DEVICE PREFIXSECONDSTAGE EFIGRUBDIR

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part [ str_dir_grub ]" \
           "$FUNCNAME 1 2" \
           "$FUNCNAME 1 3 /boot/grubPARTITION" 
    return 
fi

# Error si no se reciben al menos 2 parámetros.
[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part [ str_dir_grub ]" || return $?

# Directorio del grub en la partición de sistema
PREFIXSECONDSTAGE="$3"

EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $?
BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2)
EFIGRUBDIR="$EFIDIR/EFI/$BOOTLABEL/boot/grub"
# Comprobamos que existe directorio
[ -d "$EFIGRUBDIR" ] || mkdir -p "$EFIGRUBDIR"
# Parcheamos uuid y particion en grub.cfg
UUID=$(blkid -o value -s UUID $(ogDiskToDev $1 $2))
DEVICE="hd$(expr $1 - 1 ),gpt$2"

cat << EOT > $EFIGRUBDIR/grub.cfg
set root='$DEVICE'
set prefix=(\$root)'${PREFIXSECONDSTAGE}/boot/grub'
configfile \$prefix/grub.cfg
EOT

# Provisional: confirmar si el segundo archivo se utiliza
cp $EFIGRUBDIR/grub.cfg "$EFIDIR/EFI/$BOOTLABEL/grub.cfg"
}


#/**
#         ogNvramInactiveEntry
#@brief   Inactiva entrada de la NVRAM identificada por la etiqueta o el orden
#@param    Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar.
#@return  (nada)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#*/ ##
function ogNvramInactiveEntry () {
local NUMENTRY

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \
           "$FUNCNAME 2" \
	   "$FUNCNAME \"Windows Boot Manager\""
    return 
fi

# Error si no se recibe 1 parámetro.
[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $?

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

# Distingo si es número de orden o etiqueta
if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then
    NUMENTRY=$( efibootmgr |awk  -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}')
else
    NUMENTRY=$(efibootmgr |awk  -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}')
fi

[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'")

efibootmgr -A -b $NUMENTRY &>/dev/null
}


#/**
#         ogNvramList
#@brief   Lista las entradas de la NVRAN (sólo equipos UEFI)
#@return  Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ]
#@exception OG_ERR_NOTUEFI  UEFI no activa.
#*/ ##
function ogNvramList () {

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME" \
           "$FUNCNAME"
    return 
fi

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

efibootmgr |awk   '{if($1~/Boot[[:digit:]]/) ; active="" ;if ($1~/*/) active="*"; if($1~/Boot[[:digit:]]/) printf  "%4s %s %s %s\n", gensub(/^0{1,3}/,"",1,substr($1,5,4))," ", substr($0, index($0,$2)), active}'
}


#/**
#         ogRestoreEfiBootLoader int_ndisk str_repo
#@brief   Copia el cargador de arranque de la partición de sistema a la partición EFI.
#@param   int_ndisk    nº de orden del disco
#@param   int_part     nº de partición
#@return  (nada, por determinar)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado (partición de sistema o EFI).
#@exception OG_ERR_NOTOS     sin sistema operativo.
#*/ ##
function ogRestoreEfiBootLoader () {
# Variables locales
local MNTDIR EFIDIR BOOTLABEL OSVERSION LOADER f UUID DEVICE

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \
           "$FUNCNAME 1 2"
    return 
fi

# Error si no se reciben 2 arámetros.
[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $?

# Comprobamos que exista partición de sistema y la  ESP
MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_PARTITION "$DISK $PART" || return $?
EFIDIR=$(ogMount $(ogGetEsp))
if [ "$EFIDIR" == "" ]; then
    ogFormat $(ogGetEsp) FAT32
    EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $?
fi

# Comprobamos que exista el cargador
#BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2)
OSVERSION=$(ogGetOsVersion $1 $2)
case $OSVERSION in
    *Windows\ 10*)
        BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2)
        LOADER=$(ogGetPath $MNTDIR/ogBoot/bootmgfw.efi)
        [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($OSVERSION, EFI)" || return $?
        [ -r $EFIDIR/EFI/$BOOTLABEL ] && rm -rf $EFIDIR/EFI/$BOOTLABEL
        mkdir -p $EFIDIR/EFI/$BOOTLABEL
        cp -r "${LOADER%/*}" $EFIDIR/EFI/$BOOTLABEL/Boot
        # Nombre OpenGnsys para cargador
        cp $LOADER $EFIDIR/EFI/$BOOTLABEL/Boot/ogloader.efi

        # Si existe subcarpeta Microsoft en la partición EFI la renombramos
        [ "$(ogGetPath $EFIDIR/EFI/Microsoft)" == "" ] || mv $EFIDIR/EFI/{Microsoft,Microsoft.backup.og}
        ;; 
esac
}


#/**
#         ogRestoreUuidPartitions
#@brief   Restaura los uuid de las particiones y la tabla de particiones
#@param   int_ndisk      nº de orden del disco
#@param   int_nfilesys   nº de orden del sistema de archivos
#@param   REPO|CACHE     repositorio
#@param   str_imgname    nombre de la imagen
#@return  (nada)
#@exception OG_ERR_FORMAT    Formato incorrecto.
#@exception OG_ERR_NOTFOUND  No encontrado fichero de información de la imagen (con uuid)
#*/ ##
function ogRestoreUuidPartitions () {
local DISK PART IMGNAME INFOFILE DEVICE DATA GUID UUID IMGGUID
local EFIDEVICE EFIDATA EFIGUID EFIUUID EFIUUID IMGEFIGUID

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME REPO|CACHE str_imgname int_ndisk int_npart" \
           "$FUNCNAME REPO Windows 1 2"
    return
fi
# Error si no se reciben 4 parámetros.
[ $# -eq 4 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME REPO|CACHE str_imgname int_ndisk int_npart" || return $?

# Sólo se ejecuta si es UEFI
ogIsEfiActive || return

# Parámetros de entrada
IMGNAME="$2"
INFOFILE="$OGIMG/.$IMGNAME.img.json"
[ "${1^^}" == "CACHE" ] && INFOFILE="$OGCAC$INFOFILE"
# TODO: que la función getPath soporte archivos ocultos
ls $INFOFILE &>/dev/null || ogRaiseError $OG_ERR_NOTFOUND "$INFOFILE" || return $?
DISK=$3
PART=$4

DEVICE=$(ogDiskToDev $DISK)
read -e EFIDISK EFIPART <<<"$(ogGetEsp)"

# Datos de la imagen
IMGGUID=$(jq .guid $INFOFILE|tr -d \")
IMGEFIGUID=$(jq .espguid $INFOFILE|tr -d \")

# Datos actuales
DATA=$(sfdisk -J $DEVICE)
GUID=$(echo $DATA|jq ".partitiontable|.id"|tr -d \")

if [ "$IMGGUID" != "$GUID" ]; then
    echo sgdisk -U "$IMGGUID"  "$DEVICE"
    sgdisk -U "$IMGGUID"  "$DEVICE"
    partprobe
fi

if [ $DISK -eq $EFIDISK ]; then
    EFIDATA=$DATA
    EFIDEVICE=$DEVICE
else
    EFIDEVICE=$(ogDiskToDev $EFIDISK) || return $?
    EFIDATA=$(sfdisk -J $EFIDEVICE)
    EFIGUID=$(echo $EFIDATA|jq ".partitiontable|.id"|tr -d \")
    if [ "$IMGEFIGUID" != "$EFIGUID" ]; then
echo         sgdisk -U "$IMGEFIGUID"  "$EFIDEVICE"
       sgdisk -U "$IMGEFIGUID"  "$EFIDEVICE"
       partprobe
   fi
fi
}


#/**
#         ogNvramSetNext
#@brief   Configura el próximo arranque con la entrada del gestor de arranque (NVRAM) identificada por la etiqueta o el orden.
#@param    Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar.
#@return  (nada)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#*/ ##
function ogNvramSetNext () {
local NUMENTRY

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \
           "$FUNCNAME 2" \
	   "$FUNCNAME \"Windows Boot Manager\""
    return
fi

# Error si no se recibe 1 parámetro.
[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $?

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

# Distingo si es número de orden o etiqueta
if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then
    NUMENTRY=$( efibootmgr |awk  -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}')
else
    NUMENTRY=$(efibootmgr |awk  -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}')
fi

[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'")

efibootmgr -n $NUMENTRY &>/dev/null
}

#/**
#         ogNvramSetOrder
#@brief   Configura el orden de las entradas de la NVRAM
#@param   Orden de las entradas separadas por espacios
#@return  (nada)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTUEFI   UEFI no activa.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado (entrada NVRAM).
#*/ ##
function ogNvramSetOrder () {
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME Num_order1 [ Num_order2 ] ... " \
           "$FUNCNAME 1 3"
    return
fi
#
# Error si no se recibe al menos 1 parámetro.
[ $# -ge 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Num_order1 [ Num_order2 ] ..." || return $?

# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

# Comprobamos que sean números
[[ "$@" =~ ^([0-9a-fA-F ]+)$ ]] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Num_order1 [ Num_order2 ] ..." || return $?

# Entradas de la NVRAM actuales
NUMENTRYS=$(efibootmgr|awk '{ if ($1~/Boot[0-9a-fA-F]{4}/) printf "0%s ", substr($1,5,4)}')

ORDER=""
for ARG in $@; do
    # Si no existe la entrada me salgo
    ARG=$(printf  %04X 0x$ARG)
    echo $NUMENTRYS | grep "$ARG" &>/dev/null || ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry order \"$ARG\"" || return $?
    ORDER=${ORDER},$ARG
done

# Cambiamos el orden
efibootmgr -o ${ORDER#,} &>/dev/null
}


#/**
#         ogNvramSetTimeout
#@brief   Configura el tiempo de espera de la NVRAM
#@param   Orden de las entradas separadas por espacios
#@return  (nada)

#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#*/ ##
function ogNvramSetTimeout () {
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME int_Timeout (seg)" \
           "$FUNCNAME 2"
    return
fi
#
# Si no es equipo UEFI salir con error
ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $?

# Error si no se recibe 1 parámetro.
[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_Timeout (seg)" || return $?

# Comprobamos que sea  un número
[[ "$1" =~ ^([0-9 ]+)*$ ]] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_Timeout (seg)" || return $?

# Cambiamos el orden
efibootmgr -t $1 &>/dev/null
}


#/**
#         ogUuidChange int_ndisk str_repo
#@brief   Reemplaza el UUID de un sistema de ficheros.
#@param   int_ndisk    nº de orden del disco
#@param   int_part     nº de partición
#@return  (nada, por determinar)
#@exception OG_ERR_FORMAT    formato incorrecto.
#@exception OG_ERR_NOTFOUND  fichero o dispositivo no encontrado.
#*/ ##
function ogUuidChange () {
local MNTDIR DEVICE UUID NEWUUID f

# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \
           "$FUNCNAME 1 2"
    return
fi

# Error si no se reciben al menos 2 parámetros.
[ $# -eq 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $?

# Comprobamos que exista la partición
MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_NOTFOUND "Device $1 $2" || return $?
DEVICE=$(ogDiskToDev $1 $2)
UUID=$(blkid -o value -s UUID $DEVICE)
NEWUUID=$(cat /proc/sys/kernel/random/uuid)

# Cambiamos UUID a la partición
ogUnmount $1 $2
tune2fs $DEVICE -U $NEWUUID

# Cambiamos UUID en la configuración (fstab y grub)
ogMount $1 $2
for f in $MNTDIR/etc/fstab $MNTDIR/{,boot/}{{grubMBR,grubPARTITION}/boot/,}{grub{,2},{,efi/}EFI/*}/{menu.lst,grub.cfg}; do
        [ -r $f ] && sed -i s/$UUID/$NEWUUID/g $f
done
}
